前回はTauri+SycamoreでYAMLの読み書きを実装しました。 今回は画面遷移を実装してみます。
前回はこちら
a3colorr.hatenablog.com
基本的には公式ドキュメントのRoutingページをなぞれば実現できるのですが、一部の説明とサンプルコードに誤りがあるようで、コピペではエラーになります。
このブログ本文中ではその部分を補完しています。
!! 2023-05-20現在、公式ドキュメントの当該サンプルコードは誤記訂正されています
公式ドキュメントのRoutingページ
https://sycamore-rs.netlify.app/docs/advanced/routing#using-router
環境
- Macbook Pro
- M1 pro
- macOS 13.3.1
- rustc 1.68.2
- tauri-build 1.3
やりたいこと
2つのページ(Home、About)を用意して、相互にページ遷移する
準備
プロジェクトルートのCargo.toml
にsycamore-router
の依存関係を追加します。
公式ドキュメントでは0.9.0-beta.1
を指定していますが、crate.io
を見ると最新のメジャーバージョンが0.8.0
だったので、今回は0.8.0
としました。
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] serde-wasm-bindgen = "0.4.3" js-sys = "0.3.59" serde = { version = "1.0.140", features = ["derive"] } wasm-bindgen = { version = "0.2.82", features = ["serde-serialize"] } wasm-bindgen-futures = "0.4.32" sycamore = { version = "0.8", features = ["suspense"] } sycamore-router = "0.8.0" <-これ
crate.ioのページ
https://crates.io/crates/sycamore-router
ちなみに、0.9.0-beta.1
にすると以下の型不一致エラーが出ます。
expected struct `sycamore::prelude::View`, found struct `sycamore_core::view::View
betaだからまた変更が入るかもしれないから気にしなくても良いんだろうか?、将来的には今動いているコードを変えないとダメなんだろうな、などと色々思うところがありました。
実装する
最初に、プロジェクトルートのsrc/app.rs
でモジュールをインポートします。
// 公式ドキュメントでは以下を指定しているが、1つ不足している。 // use sycamore_router::{Route, Router, RouterProps}; // 正しくは次の通り。 // `RouterProps`は今回使用しないので、外しても良い。 use sycamore_router::{Route, Router, HistoryIntegration, RouterProps};
次に、ルーティング用のenum
を追加します。
#[derive(Route)] enum AppRoutes { #[to("/")] Home, #[to("/about")] About, #[not_found] NotFound }
各値(バリアント)には、#[to(_)]
属性または#[not_found]
属性のいずれかを指定します。
例えば、Home
ページ(ルートページ)には#[to("/")]
、About
ページ(サブページ)には#[to("/about")]
を指定します。
一方、#[not_found]
は、他のすべてのルートが一致しない場合に遷移するルートに指定します。#[not_found]
のルートが無いとコンパイルエラーになります。また、#[not_found]
を指定できるルートは 1 つだけです。
最後に、ViewにRouter
を追加します。
(この辺りは、ネストが深くて見づらくなります。。。)
公式ドキュメントに載っているRouter
のサンプルコードは、いくつかのview!{}
でcx
の指定が抜けているため、サンプルコードをコピペしてもコンパイルエラーになります。
!! 2023-05-20現在、公式ドキュメントの当該サンプルコードは誤記訂正されています
// 予期しない入力(引数に`cx`を渡してください) unexpected end of input, expected `,` (help: make sure you pass the cx variable to the macro as an argument)
cx
を追加した様子。
view! {cx, Router( integration = HistoryIntegration::new(), view=|cx, route: &ReadSignal<AppRoutes>| { view! {cx, div(class="app") { (match route.get().as_ref() { AppRoutes::Home => view! {cx, main(class="container") { "Home Page" a(href="/about") { "to About" } } }, AppRoutes::About => view! {cx, main(class="container") { "About Page" div { a(href="/") { "to Home" } } div { a(href="/not-found") { "to NotFound" } } } }, AppRoutes::NotFound => view! {cx, main(class="container") { "Not Found" div { a(href="/") { "to Home" } } } } }) } } } ) }
動作している様子
cargo tauri dev
で動作確認をします。
ビルドエラー等がなければ、次のように動作します。