From 07446386e63b83ede2f852309bb5a73b9346ed56 Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Thu, 1 Jun 2023 14:10:33 -0500 Subject: [PATCH] fix external router examples --- examples/router.rs | 172 ++++++++++-------- .../examples/axum-router/src/main.rs | 76 +++++--- packages/router/src/components/router.rs | 10 +- packages/router/src/contexts/router.rs | 10 +- packages/router/src/history/memory.rs | 12 +- packages/router/src/lib.rs | 2 +- packages/router/src/router_cfg.rs | 8 +- 7 files changed, 157 insertions(+), 133 deletions(-) diff --git a/examples/router.rs b/examples/router.rs index a71ca144f..2f6251968 100644 --- a/examples/router.rs +++ b/examples/router.rs @@ -4,97 +4,109 @@ use dioxus::prelude::*; use dioxus_router::prelude::*; fn main() { - dioxus_desktop::launch(app); + #[cfg(target_arch = "wasm32")] + dioxus_web::launch(App); + #[cfg(not(target_arch = "wasm32"))] + dioxus_desktop::launch(App); } -fn app(cx: Scope) -> Element { - use_router(cx, &RouterConfiguration::default, &|| { - Segment::content(comp(Home)) - .fixed( - "users", - Route::empty() - .nested(Segment::content(comp(UserList)).catch_all((comp(User), UserId {}))), - ) - .fixed( - "blog", - Route::empty().nested( - Segment::content(comp(BlogList)).catch_all((comp(BlogPost), PostId {})), - ), - ) - .fallback(comp(E404)) - }); - - cx.render(rsx! { - ul { - li { Link { target: "/", "Go home!" } } - li { Link { target: "/users", "List all users" } } - li { Link { target: "/blog", "Blog posts" }} - } - - Outlet { } - }) +// ANCHOR: router +#[derive(Routable, Clone)] +#[rustfmt::skip] +enum Route { + #[layout(NavBar)] + #[route("/")] + Home {}, + #[nest("/blog")] + #[layout(Blog)] + #[route("/")] + BlogList {}, + #[route("/blog/:name")] + BlogPost { name: String }, + #[end_layout] + #[end_nest] + #[end_layout] + #[nest("/myblog")] + #[redirect("/", || Route::BlogList {})] + #[redirect("/:name", |name: String| Route::BlogPost { name })] + #[end_nest] + #[route("/:...route")] + PageNotFound { + route: Vec, + }, } +// ANCHOR_END: router -fn Home(cx: Scope) -> Element { - render!(h1 { "Home" }) -} - -fn BlogList(cx: Scope) -> Element { +fn App(cx: Scope) -> Element { render! { - h1 { "Blog Posts" } - ul { - li { Link { target: "/blog/1", "First blog post" } } - li { Link { target: "/blog/2", "Second blog post" } } - li { Link { target: "/blog/3", "Third blog post" } } - } + Router {} } } -struct PostId; -fn BlogPost(cx: Scope) -> Element { - let post = use_route(cx)?.parameter::().unwrap(); - - cx.render(rsx! { - div { - h1 { "Reading blog post: {post}" } - p { "example blog post" } - } - }) -} - -fn UserList(cx: Scope) -> Element { +#[inline_props] +fn NavBar(cx: Scope) -> Element { render! { - h1 { "Users" } - ul { - li { Link { target: "/users/bill", "Bill" } } - li { Link { target: "/users/jeremy", "Jeremy" } } - li { Link { target: "/users/adrian", "Adrian" } } - } - } -} - -struct UserId; -fn User(cx: Scope) -> Element { - let state = use_route(cx)?; - - let user = state.parameter::().unwrap(); - - let query = state.query.as_ref().cloned().unwrap_or_default(); - let bold = query.contains("bold") && !query.contains("bold=false"); - - cx.render(rsx! { - div { - h1 { "Showing user: {user}" } - - if bold { - rsx!{ b { "bold" } } - } else { - rsx!{ i { "italic" } } + nav { + ul { + li { Link { target: Route::Home {}, "Home" } } + li { Link { target: Route::BlogList {}, "Blog" } } } } - }) + Outlet {} + } } -fn E404(cx: Scope) -> Element { - render!(h1 { "Error 404 - Page not Found" }) +#[inline_props] +fn Home(cx: Scope) -> Element { + render! { + h1 { "Welcome to the Dioxus Blog!" } + } +} + +#[inline_props] +fn Blog(cx: Scope) -> Element { + render! { + h1 { "Blog" } + Outlet {} + } +} + +#[inline_props] +fn BlogList(cx: Scope) -> Element { + render! { + h2 { "Choose a post" } + ul { + li { + Link { + target: Route::BlogPost { name: "Blog post 1".into() }, + "Read the first blog post" + } + } + li { + Link { + target: Route::BlogPost { name: "Blog post 2".into() }, + "Read the second blog post" + } + } + } + } +} + +#[inline_props] +fn BlogPost(cx: Scope, name: String) -> Element { + render! { + h2 { "Blog Post: {name}"} + } +} + +#[inline_props] +fn PageNotFound(cx: Scope, route: Vec) -> Element { + render! { + h1 { "Page not found" } + p { "We are terribly sorry, but the page you requested doesn't exist." } + pre { + color: "red", + "log:\nattemped to navigate to: {route:?}" + } + } } diff --git a/packages/fullstack/examples/axum-router/src/main.rs b/packages/fullstack/examples/axum-router/src/main.rs index 96567c791..81ea31ddb 100644 --- a/packages/fullstack/examples/axum-router/src/main.rs +++ b/packages/fullstack/examples/axum-router/src/main.rs @@ -8,7 +8,7 @@ #![allow(non_snake_case)] use dioxus::prelude::*; use dioxus_fullstack::prelude::*; -use dioxus_router::*; +use dioxus_router::prelude::*; use serde::{Deserialize, Serialize}; fn main() { @@ -34,6 +34,8 @@ fn main() { })); use axum::extract::State; + use std::str::FromStr; + PostServerData::register().unwrap(); GetServerData::register().unwrap(); tokio::runtime::Runtime::new() @@ -57,7 +59,7 @@ fn main() { &ServeConfigBuilder::new( App, AppProps { - route: Some(format!("http://{addr}{uri}")), + route: Route::from_str(&uri.to_string()).ok(), }, ) .build(), @@ -74,48 +76,64 @@ fn main() { } } -#[derive(Clone, Debug, Props, PartialEq, Serialize, Deserialize)] -struct AppProps { - route: Option, +#[derive(Clone, Routable, Serialize, Deserialize, Debug, PartialEq)] +enum Route { + #[route("/")] + Home {}, + #[route("/blog")] + Blog {}, } -fn App(cx: Scope) -> Element { - cx.render(rsx! { - Router { - initial_url: cx.props.route.clone(), - - Route { to: "/blog", - Link { - to: "/", - "Go to counter" - } - table { - tbody { +#[inline_props] +fn Blog(cx: Scope) -> Element { + render! { + Link { + target: Route::Home {}, + "Go to counter" + } + table { + tbody { + for _ in 0..100 { + tr { for _ in 0..100 { - tr { - for _ in 0..100 { - td { "hello world!" } - } - } + td { "hello world!" } } } } - }, - // Fallback - Route { to: "", - Counter {} - }, + } + } + } +} + +#[derive(Clone, Debug, Props, PartialEq, Serialize, Deserialize)] +struct AppProps { + route: Option, +} + +fn App(cx: Scope) -> Element { + #[cfg(feature = "ssr")] + let initial_route = cx.props.route.clone().unwrap_or(Route::Home {}); + cx.render(rsx! { + Router { + config: move || RouterConfig::default().history({ + #[cfg(feature = "ssr")] + let history = MemoryHistory::with_initial_path(initial_route); + #[cfg(feature = "web")] + let history = WebHistory::default(); + history + }) } }) } -fn Counter(cx: Scope) -> Element { +#[inline_props] +fn Home(cx: Scope) -> Element { let mut count = use_state(cx, || 0); let text = use_state(cx, || "...".to_string()); cx.render(rsx! { Link { - to: "/blog", + target: Route::Blog {} "Go to blog" } div{ diff --git a/packages/router/src/components/router.rs b/packages/router/src/components/router.rs index aeab7b815..e62f48c64 100644 --- a/packages/router/src/components/router.rs +++ b/packages/router/src/components/router.rs @@ -5,13 +5,13 @@ use std::{cell::RefCell, str::FromStr}; use crate::{ prelude::{GenericOutlet, GenericRouterContext}, routable::Routable, - router_cfg::RouterConfiguration, + router_cfg::RouterConfig, }; /// The config for [`GenericRouter`]. pub struct RouterConfigFactory { #[allow(clippy::type_complexity)] - config: RefCell RouterConfiguration>>>, + config: RefCell RouterConfig>>>, } impl Default for RouterConfigFactory @@ -19,13 +19,11 @@ where ::Err: std::fmt::Display, { fn default() -> Self { - Self::from(RouterConfiguration::default) + Self::from(RouterConfig::default) } } -impl RouterConfiguration + 'static> From - for RouterConfigFactory -{ +impl RouterConfig + 'static> From for RouterConfigFactory { fn from(value: F) -> Self { Self { config: RefCell::new(Some(Box::new(value))), diff --git a/packages/router/src/contexts/router.rs b/packages/router/src/contexts/router.rs index 1bc320f13..a94fb5167 100644 --- a/packages/router/src/contexts/router.rs +++ b/packages/router/src/contexts/router.rs @@ -7,7 +7,7 @@ use dioxus::prelude::*; use crate::{ history::HistoryProvider, navigation::NavigationTarget, routable::Routable, - router_cfg::RouterConfiguration, + router_cfg::RouterConfig, }; /// An error that can occur when navigating. @@ -15,7 +15,8 @@ use crate::{ pub struct ExternalNavigationFailure(String); /// A function the router will call after every routing update. -pub(crate) type RoutingCallback = Arc) -> Option>>; +pub(crate) type RoutingCallback = + Arc) -> Option>>; struct MutableRouterState where @@ -70,10 +71,7 @@ impl GenericRouterContext where R: Routable, { - pub(crate) fn new( - cfg: RouterConfiguration, - mark_dirty: Arc, - ) -> Self + pub(crate) fn new(cfg: RouterConfig, mark_dirty: Arc) -> Self where R: Clone, { diff --git a/packages/router/src/history/memory.rs b/packages/router/src/history/memory.rs index 0c535906a..ce1ae72a2 100644 --- a/packages/router/src/history/memory.rs +++ b/packages/router/src/history/memory.rs @@ -33,17 +33,15 @@ where /// OtherPage {}, /// } /// - /// let mut history = MemoryHistory::::with_initial_path("/").unwrap(); + /// let mut history = MemoryHistory::::with_initial_path(Route::Index {}).unwrap(); /// assert_eq!(history.current_route(), Route::Index {}); /// assert_eq!(history.can_go_back(), false); /// ``` - pub fn with_initial_path(path: impl AsRef) -> Result::Err> { - let path = path.as_ref(); - - Ok(Self { - current: R::from_str(path)?, + pub fn with_initial_path(path: R) -> Self { + Self { + current: path, ..Default::default() - }) + } } } diff --git a/packages/router/src/lib.rs b/packages/router/src/lib.rs index 76cfc2068..4beeac5de 100644 --- a/packages/router/src/lib.rs +++ b/packages/router/src/lib.rs @@ -56,7 +56,7 @@ pub mod prelude { pub use crate::hooks::*; pub use crate::navigation::*; pub use crate::routable::*; - pub use crate::router_cfg::RouterConfiguration; + pub use crate::router_cfg::RouterConfig; pub use dioxus_router_macro::Routable; #[doc(hidden)] diff --git a/packages/router/src/router_cfg.rs b/packages/router/src/router_cfg.rs index 46b3df2df..4422f4295 100644 --- a/packages/router/src/router_cfg.rs +++ b/packages/router/src/router_cfg.rs @@ -23,15 +23,15 @@ use crate::prelude::*; /// #[route("/")] /// Index {}, /// } -/// let cfg = RouterConfiguration::default().history(WebHistory::default()); +/// let cfg = RouterConfig::default().history(WebHistory::default()); /// ``` -pub struct RouterConfiguration { +pub struct RouterConfig { pub(crate) failure_external_navigation: fn(Scope) -> Element, pub(crate) history: Box>, pub(crate) on_update: Option>, } -impl Default for RouterConfiguration +impl Default for RouterConfig where ::Err: std::fmt::Display, { @@ -50,7 +50,7 @@ where } } -impl RouterConfiguration { +impl RouterConfig { /// A function to be called whenever the routing is updated. /// /// The callback is invoked after the routing is updated, but before components and hooks are