update router book

This commit is contained in:
Adrian Wannenmacher 2022-12-16 10:41:44 +01:00
parent 1890ebc4f7
commit a947ce2215
No known key found for this signature in database
GPG key ID: 19D986ECB1E492D5
23 changed files with 212 additions and 212 deletions

View file

@ -17,11 +17,11 @@ Let's create a new `NavBar` component:
# use dioxus_router::prelude::*; # use dioxus_router::prelude::*;
# #
fn NavBar(cx: Scope) -> Element { fn NavBar(cx: Scope) -> Element {
cx.render(rsx! { render! {
nav { nav {
ul { } ul { }
} }
}) }
} }
``` ```
@ -40,7 +40,7 @@ more on other targets later) and an element. Let's add our links
# use dioxus_router::prelude::*; # use dioxus_router::prelude::*;
# #
fn NavBar(cx: Scope) -> Element { fn NavBar(cx: Scope) -> Element {
cx.render(rsx! { render! {
nav { nav {
ul { ul {
// new stuff starts here // new stuff starts here
@ -55,7 +55,7 @@ fn NavBar(cx: Scope) -> Element {
// new stuff ends here // new stuff ends here
} }
} }
}) }
} }
``` ```
@ -81,10 +81,10 @@ fn App(cx: Scope) -> Element {
&|| Segment::content(comp(Home)).fallback(comp(PageNotFound)) &|| Segment::content(comp(Home)).fallback(comp(PageNotFound))
); );
cx.render(rsx! { render! {
NavBar { } // this is new NavBar { } // this is new
Outlet { } Outlet { }
}) }
} }
``` ```
Now you should see a list of links near the top of your page. Click on one and Now you should see a list of links near the top of your page. Click on one and
@ -103,7 +103,7 @@ in that case.
# use dioxus_router::prelude::*; # use dioxus_router::prelude::*;
# #
fn NavBar(cx: Scope) -> Element { fn NavBar(cx: Scope) -> Element {
cx.render(rsx! { render! {
nav { nav {
ul { ul {
li { Link { li { Link {
@ -118,7 +118,7 @@ fn NavBar(cx: Scope) -> Element {
} } } }
} }
} }
}) }
} }
``` ```
@ -149,10 +149,10 @@ us to add a heading that tells the user they are on the blog.
# use dioxus_router::prelude::*; # use dioxus_router::prelude::*;
# #
fn Blog(cx: Scope) -> Element { fn Blog(cx: Scope) -> Element {
cx.render(rsx! { render! {
h1 { "Blog" } h1 { "Blog" }
Outlet {} Outlet {}
}) }
} }
``` ```
@ -170,7 +170,7 @@ is selected:
# use dioxus_router::prelude::*; # use dioxus_router::prelude::*;
# #
fn BlogList(cx: Scope) -> Element { fn BlogList(cx: Scope) -> Element {
cx.render(rsx! { render! {
h2 { "Choose a post" } h2 { "Choose a post" }
ul { ul {
li { Link { li { Link {
@ -182,7 +182,7 @@ fn BlogList(cx: Scope) -> Element {
"Read the second blog post" "Read the second blog post"
} } } }
} }
}) }
} }
``` ```
@ -199,16 +199,16 @@ parameters:
struct PostId; struct PostId;
fn BlogPost(cx: Scope) -> Element { fn BlogPost(cx: Scope) -> Element {
let route = use_route(&cx).unwrap(); let route = use_route(cx).unwrap();
let post_id = route.parameter::<PostId>(); let post_id = route.parameter::<PostId>();
let post = post_id let post = post_id
.map(|id| id.to_string()) .map(|id| id.to_string())
.unwrap_or(String::from("unknown")); .unwrap_or(String::from("unknown"));
cx.render(rsx! { render! {
h2 { "Blog Post: {post}"} h2 { "Blog Post: {post}"}
}) }
} }
``` ```
@ -243,10 +243,10 @@ fn App(cx: Scope) -> Element {
} }
); );
cx.render(rsx! { render! {
NavBar { } NavBar { }
Outlet { } Outlet { }
}) }
} }
``` ```

View file

@ -22,38 +22,38 @@ fn App(cx: Scope) -> Element {
} }
); );
cx.render(rsx! { render! {
NavBar {} NavBar {}
Outlet {} Outlet {}
}) }
} }
fn NavBar(cx: Scope) -> Element { fn NavBar(cx: Scope) -> Element {
cx.render(rsx! { render! {
nav { nav {
ul { ul {
li { Link { target: named::<RootIndex>(), "Home" } } li { Link { target: named::<RootIndex>(), "Home" } }
li { Link { target: "/blog", "Blog" } } li { Link { target: "/blog", "Blog" } }
} }
} }
}) }
} }
fn Home(cx: Scope) -> Element { fn Home(cx: Scope) -> Element {
cx.render(rsx! { render! {
h1 { "Welcome to the Dioxus Blog!" } h1 { "Welcome to the Dioxus Blog!" }
}) }
} }
fn Blog(cx: Scope) -> Element { fn Blog(cx: Scope) -> Element {
cx.render(rsx! { render! {
h1 { "Blog" } h1 { "Blog" }
Outlet {} Outlet {}
}) }
} }
fn BlogList(cx: Scope) -> Element { fn BlogList(cx: Scope) -> Element {
cx.render(rsx! { render! {
h2 { "Choose a post" } h2 { "Choose a post" }
ul { ul {
li { Link { li { Link {
@ -65,27 +65,27 @@ fn BlogList(cx: Scope) -> Element {
"Read the second blog post" "Read the second blog post"
} } } }
} }
}) }
} }
struct PostId; struct PostId;
struct BlogPostName; struct BlogPostName;
fn BlogPost(cx: Scope) -> Element { fn BlogPost(cx: Scope) -> Element {
let route = use_route(&cx).unwrap(); let route = use_route(cx).unwrap();
let post_id = route.parameter::<PostId>(); let post_id = route.parameter::<PostId>();
let post = post_id let post = post_id
.map(|id| id.to_string()) .map(|id| id.to_string())
.unwrap_or(String::from("unknown")); .unwrap_or(String::from("unknown"));
cx.render(rsx! { render! {
h2 { "Blog Post: {post}"} h2 { "Blog Post: {post}"}
}) }
} }
fn PageNotFound(cx: Scope) -> Element { fn PageNotFound(cx: Scope) -> Element {
cx.render(rsx! { render! {
h1 { "Page not found" } h1 { "Page not found" }
p { "We are terribly sorry, but the page you requested doesn't exist." } p { "We are terribly sorry, but the page you requested doesn't exist." }
}) }
} }

View file

@ -14,9 +14,9 @@ First we need an actual page to route to! Let's add a homepage component:
# use dioxus::prelude::*; # use dioxus::prelude::*;
# #
fn Home(cx: Scope) -> Element { fn Home(cx: Scope) -> Element {
cx.render(rsx! { render! {
h1 { "Welcome to the Dioxus Blog!" } h1 { "Welcome to the Dioxus Blog!" }
}) }
} }
``` ```
@ -49,9 +49,9 @@ fn App(cx: Scope) -> Element {
&|| Segment::content(comp(Home)) &|| Segment::content(comp(Home))
); );
cx.render(rsx! { render! {
Outlet { } Outlet { }
}) }
} }
``` ```
@ -74,10 +74,10 @@ First, we create a new `PageNotFound` component.
# use dioxus::prelude::*; # use dioxus::prelude::*;
# #
fn PageNotFound(cx: Scope) -> Element { fn PageNotFound(cx: Scope) -> Element {
cx.render(rsx! { render! {
h1 { "Page not found" } h1 { "Page not found" }
p { "We are terribly sorry, but the page you requested doesn't exist." } p { "We are terribly sorry, but the page you requested doesn't exist." }
}) }
} }
``` ```
@ -101,9 +101,9 @@ fn App(cx: Scope) -> Element {
} }
); );
cx.render(rsx! { render! {
Outlet { } Outlet { }
}) }
} }
``` ```

View file

@ -25,7 +25,7 @@ If we need a link to an external page we can do it like this:
# use dioxus_router::prelude::*; # use dioxus_router::prelude::*;
# #
fn GoToDioxus(cx: Scope) -> Element { fn GoToDioxus(cx: Scope) -> Element {
cx.render(rsx! { render! {
Link { Link {
target: NavigationTarget::External("https://dioxuslabs.com".into()), target: NavigationTarget::External("https://dioxuslabs.com".into()),
"Explicit ExternalTarget target" "Explicit ExternalTarget target"
@ -34,7 +34,7 @@ fn GoToDioxus(cx: Scope) -> Element {
target: "https://dioxuslabs.com", // short form target: "https://dioxuslabs.com", // short form
"Implicit ExternalTarget target" "Implicit ExternalTarget target"
} }
}) }
} }
``` ```
@ -105,7 +105,7 @@ Now we can change the targets of the links in our `BlogList` component.
# fn BlogPost(cx: Scope) -> Element { unimplemented!() } # fn BlogPost(cx: Scope) -> Element { unimplemented!() }
# #
fn BlogList(cx: Scope) -> Element { fn BlogList(cx: Scope) -> Element {
cx.render(rsx! { render! {
h2 { "Choose a post" } h2 { "Choose a post" }
ul { ul {
li { Link { li { Link {
@ -119,7 +119,7 @@ fn BlogList(cx: Scope) -> Element {
"Read the second blog post" "Read the second blog post"
} } } }
} }
}) }
} }
``` ```
@ -142,14 +142,14 @@ We can change the link in our `NavBar` component to take advantage of that.
# use dioxus_router::prelude::*; # use dioxus_router::prelude::*;
# #
fn NavBar(cx: Scope) -> Element { fn NavBar(cx: Scope) -> Element {
cx.render(rsx! { render! {
nav { nav {
ul { ul {
li { Link { target: named::<RootIndex>(), "Home" } } li { Link { target: named::<RootIndex>(), "Home" } }
li { Link { target: "/blog", "Blog" } } li { Link { target: "/blog", "Blog" } }
} }
} }
}) }
} }
``` ```

View file

@ -35,23 +35,23 @@ You can override it by setting the `failure_external_navigation` value of the
# extern crate dioxus_router; # extern crate dioxus_router;
# use dioxus_router::prelude::*; # use dioxus_router::prelude::*;
fn ExternalNavigationFallback(cx: Scope) -> Element { fn ExternalNavigationFallback(cx: Scope) -> Element {
let route = use_route(&cx).expect("is nested within a Router component"); let route = use_route(cx).expect("is nested within a Router component");
let url = route let url = route
.parameter::<FailureExternalNavigation>() .parameter::<FailureExternalNavigation>()
.unwrap_or_default(); .unwrap_or_default();
cx.render(rsx! { render! {
h1 { "External navigation failure!" } h1 { "External navigation failure!" }
Link { Link {
target: url, target: url,
"Go to external site" "Go to external site"
} }
}) }
} }
fn App(cx: Scope) -> Element { fn App(cx: Scope) -> Element {
use_router( use_router(
&cx, cx,
&|| RouterConfiguration { &|| RouterConfiguration {
failure_external_navigation: comp(ExternalNavigationFallback), failure_external_navigation: comp(ExternalNavigationFallback),
..Default::default() ..Default::default()
@ -59,9 +59,9 @@ fn App(cx: Scope) -> Element {
&|| Segment::empty() &|| Segment::empty()
); );
cx.render(rsx! { render! {
Outlet { } Outlet { }
}) }
} }
``` ```

View file

@ -37,14 +37,14 @@ You can override it by setting the `failure_named_navigation` value of the
# extern crate dioxus_router; # extern crate dioxus_router;
# use dioxus_router::prelude::*; # use dioxus_router::prelude::*;
fn NamedNavigationFallback(cx: Scope) -> Element { fn NamedNavigationFallback(cx: Scope) -> Element {
cx.render(rsx! { render! {
h1 { "Named navigation failure!" } h1 { "Named navigation failure!" }
}) }
} }
fn App(cx: Scope) -> Element { fn App(cx: Scope) -> Element {
use_router( use_router(
&cx, cx,
&|| RouterConfiguration { &|| RouterConfiguration {
failure_named_navigation: comp(NamedNavigationFallback), failure_named_navigation: comp(NamedNavigationFallback),
..Default::default() ..Default::default()
@ -52,9 +52,9 @@ fn App(cx: Scope) -> Element {
&|| Segment::empty() &|| Segment::empty()
); );
cx.render(rsx! { render! {
Outlet { } Outlet { }
}) }
} }
``` ```

View file

@ -22,14 +22,14 @@ use dioxus::prelude::*;
use dioxus_router::prelude::*; use dioxus_router::prelude::*;
fn HistoryNavigation(cx: Scope) -> Element { fn HistoryNavigation(cx: Scope) -> Element {
cx.render(rsx! { render! {
GoBackButton { GoBackButton {
"Back to the Past" "Back to the Past"
} }
GoForwardButton { GoForwardButton {
"Back to the Future" /* You see what I did there? 😉 */ "Back to the Future" /* You see what I did there? 😉 */
} }
}) }
} }
``` ```

View file

@ -24,7 +24,7 @@ use dioxus_router::{prelude::*, history::WebHashHistory};
fn App(cx: Scope) -> Element { fn App(cx: Scope) -> Element {
use_router( use_router(
&cx, cx,
&|| RouterConfiguration { &|| RouterConfiguration {
history: Box::new(WebHashHistory::new(true)), history: Box::new(WebHashHistory::new(true)),
..Default::default() ..Default::default()
@ -32,9 +32,9 @@ fn App(cx: Scope) -> Element {
&|| Segment::empty() &|| Segment::empty()
); );
cx.render(rsx! { render! {
Outlet { } Outlet { }
}) }
} }
``` ```

View file

@ -24,7 +24,7 @@ fn App(cx: Scope) -> Element {
// Here we add the router. All components inside `App` have access to its // Here we add the router. All components inside `App` have access to its
// functionality. // functionality.
let routes = use_router( let routes = use_router(
&cx, cx,
// The router can be configured with this parameter. // The router can be configured with this parameter.
&|| RouterConfiguration { &|| RouterConfiguration {
# synchronous: true, # synchronous: true,
@ -35,12 +35,12 @@ fn App(cx: Scope) -> Element {
&|| Segment::empty() &|| Segment::empty()
); );
cx.render(rsx! { render! {
h1 { "Our sites title" } h1 { "Our sites title" }
// The Outlet tells the Router where to render active content. // The Outlet tells the Router where to render active content.
Outlet { } Outlet { }
}) }
} }
# #
# let mut vdom = VirtualDom::new(App); # let mut vdom = VirtualDom::new(App);

View file

@ -25,7 +25,7 @@ use dioxus_router::prelude::*;
fn App(cx: Scope) -> Element { fn App(cx: Scope) -> Element {
use_router( use_router(
&cx, cx,
&|| RouterConfiguration { &|| RouterConfiguration {
# synchronous: true, # synchronous: true,
..Default::default() ..Default::default()
@ -33,7 +33,7 @@ fn App(cx: Scope) -> Element {
&|| Segment::empty() &|| Segment::empty()
); );
cx.render(rsx! { render! {
// links need to be inside a router, even if they navigate to an // links need to be inside a router, even if they navigate to an
// external page // external page
Link { Link {
@ -44,7 +44,7 @@ fn App(cx: Scope) -> Element {
target: "https://dioxuslabs.com/", // short form target: "https://dioxuslabs.com/", // short form
"Go to the dioxus home page 2" "Go to the dioxus home page 2"
} }
}) }
} }
# #
# let mut vdom = VirtualDom::new(App); # let mut vdom = VirtualDom::new(App);

View file

@ -24,7 +24,7 @@ use like this:
# extern crate dioxus_router; # extern crate dioxus_router;
# use dioxus_router::prelude::*; # use dioxus_router::prelude::*;
fn SomeComponent(cx: Scope) -> Element { fn SomeComponent(cx: Scope) -> Element {
cx.render(rsx! { render! {
Link { Link {
target: NavigationTarget::Internal(String::from("/some/path")), target: NavigationTarget::Internal(String::from("/some/path")),
"Link text" "Link text"
@ -33,18 +33,18 @@ fn SomeComponent(cx: Scope) -> Element {
target: "/some/path", // short form target: "/some/path", // short form
"Other link text" "Other link text"
} }
}) }
} }
``` ```
The `target` in the example above is similar to the `href` of a regular anchor The `target` in the example above is similar to the `href` of a regular anchor
element. However, it tells the router more about what kind of navigation it element. However, it tells the router more about what kind of navigation it
should perform: should perform:
- The example uses [`InternalTarget`]. We give it an arbitrary path that will be - The example uses [`Internal`]. We give it an arbitrary path that will be
merged with the current URL. merged with the current URL.
- [`NamedTarget`] allows us to navigate within our app using predefined names. - [`Named`] allows us to navigate within our app using predefined names.
See the chapter about [named navigation](./name.md) for more details. See the chapter about [named navigation](./name.md) for more details.
- [`ExternalTarget`] allows us to navigate to URLs outside of our app. See the - [`External`] allows us to navigate to URLs outside of our app. See the
chapter about [external navigation](./external.md) for more details. chapter about [external navigation](./external.md) for more details.
> The [`Link`] accepts several props that modify its behavior. See the API docs > The [`Link`] accepts several props that modify its behavior. See the API docs

View file

@ -39,25 +39,25 @@ use dioxus_router::prelude::*;
struct TargetName; struct TargetName;
fn Source(cx: Scope) -> Element { fn Source(cx: Scope) -> Element {
cx.render(rsx! { render! {
Link { Link {
// instead of InternalTarget we use NamedTarget (via the `named` fn) // instead of InternalTarget we use NamedTarget (via the `named` fn)
// we can use the returned value to add parameters or a query // we can use the returned value to add parameters or a query
target: named::<TargetName>().query("query"), target: named::<TargetName>().query("query"),
"Go to target" "Go to target"
} }
}) }
} }
fn Target(cx: Scope) -> Element { fn Target(cx: Scope) -> Element {
cx.render(rsx! { render! {
h1 { "Target" } h1 { "Target" }
}) }
} }
fn App(cx: Scope) -> Element { fn App(cx: Scope) -> Element {
use_router( use_router(
&cx, cx,
&|| RouterConfiguration { &|| RouterConfiguration {
# synchronous: true, # synchronous: true,
..Default::default() ..Default::default()
@ -71,9 +71,9 @@ fn App(cx: Scope) -> Element {
} }
); );
cx.render(rsx! { render! {
Outlet { } Outlet { }
}) }
} }
# #
# let mut vdom = VirtualDom::new(App); # let mut vdom = VirtualDom::new(App);
@ -103,7 +103,7 @@ use dioxus_router::prelude::*;
struct SomeName; struct SomeName;
fn Content(cx: Scope) -> Element { fn Content(cx: Scope) -> Element {
let route = use_route(&cx).expect("needs to be in router"); let route = use_route(cx).expect("needs to be in router");
if route.is_at(&named::<SomeName>(), false) { if route.is_at(&named::<SomeName>(), false) {
// do something // do something

View file

@ -15,7 +15,7 @@ use dioxus::prelude::*;
use dioxus_router::prelude::*; use dioxus_router::prelude::*;
fn Content(cx: Scope) -> Element { fn Content(cx: Scope) -> Element {
let nav = use_navigate(&cx).expect("called inside a router"); let nav = use_navigate(cx).expect("called inside a router");
// ... // ...
# unimplemented!() # unimplemented!()
@ -40,7 +40,7 @@ We can use the [`Navigator`] to trigger four different kinds of navigation:
# use dioxus_router::prelude::*; # use dioxus_router::prelude::*;
# #
fn Content(cx: Scope) -> Element { fn Content(cx: Scope) -> Element {
let nav = use_navigate(&cx).expect("called inside a router"); let nav = use_navigate(cx).expect("called inside a router");
// push // push
nav.push("/target"); nav.push("/target");

View file

@ -12,14 +12,14 @@ the active routes content will be rendered within the [`Outlet`].
# extern crate dioxus_ssr; # extern crate dioxus_ssr;
fn Index(cx: Scope) -> Element { fn Index(cx: Scope) -> Element {
cx.render(rsx! { render! {
h1 { "Index" } h1 { "Index" }
}) }
} }
fn App(cx: Scope) -> Element { fn App(cx: Scope) -> Element {
use_router( use_router(
&cx, cx,
&|| RouterConfiguration { &|| RouterConfiguration {
# synchronous: true, # synchronous: true,
..Default::default() ..Default::default()
@ -27,11 +27,11 @@ fn App(cx: Scope) -> Element {
&|| Segment::content(comp(Index)) &|| Segment::content(comp(Index))
); );
cx.render(rsx! { render! {
header { "header" } header { "header" }
Outlet { } Outlet { }
footer { "footer" } footer { "footer" }
}) }
} }
# #
# let mut vdom = VirtualDom::new(App); # let mut vdom = VirtualDom::new(App);
@ -84,21 +84,21 @@ put the side content.
# #
fn Main(cx: Scope) -> Element { fn Main(cx: Scope) -> Element {
cx.render(rsx! { render! {
main { "Main Content" } main { "Main Content" }
}) }
} }
struct AsideName; struct AsideName;
fn Aside(cx: Scope) -> Element { fn Aside(cx: Scope) -> Element {
cx.render(rsx! { render! {
aside { "Side Content" } aside { "Side Content" }
}) }
} }
fn App(cx: Scope) -> Element { fn App(cx: Scope) -> Element {
use_router( use_router(
&cx, cx,
&|| RouterConfiguration { &|| RouterConfiguration {
# synchronous: true, # synchronous: true,
..Default::default() ..Default::default()
@ -111,12 +111,12 @@ fn App(cx: Scope) -> Element {
} }
); );
cx.render(rsx! { render! {
Outlet { } Outlet { }
Outlet { Outlet {
name: Name::of::<AsideName>() name: Name::of::<AsideName>()
} }
}) }
} }
# #
# let mut vdom = VirtualDom::new(App); # let mut vdom = VirtualDom::new(App);
@ -152,21 +152,21 @@ easy to create an unterminated recursion. See below for an example of that.
# extern crate dioxus_ssr; # extern crate dioxus_ssr;
# #
fn RootContent(cx: Scope) -> Element { fn RootContent(cx: Scope) -> Element {
cx.render(rsx! { render! {
h1 { "Root" } h1 { "Root" }
Outlet { } Outlet { }
}) }
} }
fn NestedContent(cx: Scope) -> Element { fn NestedContent(cx: Scope) -> Element {
cx.render(rsx! { render! {
h2 { "Nested" } h2 { "Nested" }
}) }
} }
fn App(cx: Scope) -> Element { fn App(cx: Scope) -> Element {
use_router( use_router(
&cx, cx,
&|| RouterConfiguration { &|| RouterConfiguration {
# synchronous: true, # synchronous: true,
# history: Box::new(MemoryHistory::with_initial_path("/root").unwrap()), # history: Box::new(MemoryHistory::with_initial_path("/root").unwrap()),
@ -182,11 +182,11 @@ fn App(cx: Scope) -> Element {
} }
); );
cx.render(rsx! { render! {
Outlet { Outlet {
depth: 1 depth: 1
} }
}) }
} }
# #
# let mut vdom = VirtualDom::new(App); # let mut vdom = VirtualDom::new(App);
@ -215,31 +215,31 @@ This code will create a crash due to an unterminated recursion using
# use dioxus_router::prelude::*; # use dioxus_router::prelude::*;
# #
fn Content(cx: Scope) -> Element { fn Content(cx: Scope) -> Element {
cx.render(rsx! { render! {
h1 { "Heyho!" } h1 { "Heyho!" }
Outlet { Outlet {
depth: 0, depth: 0,
} }
}) }
} }
fn App(cx: Scope) -> Element { fn App(cx: Scope) -> Element {
use_router(&cx, &Default::default, &|| Segment::content(comp(Content))); use_router(cx, &Default::default, &|| Segment::content(comp(Content)));
cx.render(rsx! { render! {
Outlet { } Outlet { }
}) }
} }
``` ```
The [`Outlet`] directly within the [`Router`] has no parent [`Outlet`], so its The [`Outlet`] in the `App` component has no parent [`Outlet`], so its depth
depth will be `0`. When rendering for the path `/`, it therefore will render the will be `0`. When rendering for the path `/`, it therefore will render the
`Content` component. `Content` component.
The `Content` component will render an `h1` and an [`Outlet`]. That [`Outlet`] The `Content` component will render an `h1` and an [`Outlet`]. That [`OUtlet`]
would usually have a depth of `1`, since its a descendant of the [`Outlet`] in would usually have a depth of `1`, since it is a descendant of the [`Outlet`] in
the [`Router`]. However, we override its depth to `0`, so it will render the the `App` component. However, we override its depth to `0`, so it will render
`Content` component. the `Content` component.
That means the `Content` component will recurse until someone (e.g. the OS) puts That means the `Content` component will recurse until someone (e.g. the OS) puts
a stop to it. a stop to it.

View file

@ -16,7 +16,7 @@ use dioxus::prelude::*;
use dioxus_router::prelude::*; use dioxus_router::prelude::*;
fn SomeComponent(cx: Scope) -> Element { fn SomeComponent(cx: Scope) -> Element {
let route = use_route(&cx).expect("nested in Router"); let route = use_route(cx).expect("nested in Router");
let query = route.query.clone().unwrap(); let query = route.query.clone().unwrap();
@ -40,7 +40,7 @@ When using [`Internal`] or [`External`] we have to append our query manually.
# use dioxus_router::prelude::*; # use dioxus_router::prelude::*;
# #
fn SomeComponent(cx: Scope) -> Element { fn SomeComponent(cx: Scope) -> Element {
cx.render(rsx! { render! {
Link { Link {
target: NavigationTarget::Internal("/some/path?query=yes".into()), target: NavigationTarget::Internal("/some/path?query=yes".into()),
"Internal target" "Internal target"
@ -49,7 +49,7 @@ fn SomeComponent(cx: Scope) -> Element {
target: NavigationTarget::External("https://dioxuslab.com?query=yes".into()), target: NavigationTarget::External("https://dioxuslab.com?query=yes".into()),
"External target" "External target"
} }
}) }
} }
``` ```
@ -66,7 +66,7 @@ a function.
# struct Target; # struct Target;
# #
fn SomeComponent(cx: Scope) -> Element { fn SomeComponent(cx: Scope) -> Element {
cx.render(rsx! { render! {
Link { Link {
target: named::<Target>().query("query=yes"), target: named::<Target>().query("query=yes"),
"Query String" "Query String"
@ -75,7 +75,7 @@ fn SomeComponent(cx: Scope) -> Element {
target: named::<Target>().query(vec![("query", "yes")]), target: named::<Target>().query(vec![("query", "yes")]),
"Query Vec" "Query Vec"
} }
}) }
} }
``` ```

View file

@ -33,14 +33,14 @@ use dioxus_router::prelude::*;
struct Name; struct Name;
fn Greeting(cx: Scope) -> Element { fn Greeting(cx: Scope) -> Element {
let route = use_route(&cx).expect("is nested within a Router component"); let route = use_route(cx).expect("is nested within a Router component");
let name = route.parameter::<Name>() let name = route.parameter::<Name>()
.map(|name| name.clone()) .map(|name| name.clone())
.unwrap_or(String::from("world")); .unwrap_or(String::from("world"));
cx.render(rsx! { render! {
p { "Hello, {name}!" } p { "Hello, {name}!" }
}) }
} }
``` ```
@ -66,7 +66,7 @@ struct Name;
fn App(cx: Scope) -> Element { fn App(cx: Scope) -> Element {
use_router( use_router(
&cx, cx,
&|| RouterConfiguration { &|| RouterConfiguration {
..Default::default() ..Default::default()
}, },
@ -120,19 +120,19 @@ by the path, i.e. `//`.
struct Name; struct Name;
fn Greeting(cx: Scope) -> Element { fn Greeting(cx: Scope) -> Element {
let route = use_route(&cx).expect("is nested within a Router component"); let route = use_route(cx).expect("is nested within a Router component");
let name = route.parameter::<Name>() let name = route.parameter::<Name>()
.map(|name| name.clone()) .map(|name| name.clone())
.unwrap_or(String::from("world")); .unwrap_or(String::from("world"));
cx.render(rsx! { render! {
p { "Hello, {name}!" } p { "Hello, {name}!" }
}) }
} }
fn App(cx: Scope) -> Element { fn App(cx: Scope) -> Element {
let routes = use_router( let routes = use_router(
&cx, cx,
&|| RouterConfiguration { &|| RouterConfiguration {
# synchronous: true, # synchronous: true,
# history: Box::new(MemoryHistory::with_initial_path("/Dioxus").unwrap()), # history: Box::new(MemoryHistory::with_initial_path("/Dioxus").unwrap()),
@ -141,9 +141,9 @@ fn App(cx: Scope) -> Element {
&|| Segment::empty().catch_all((comp(Greeting), Name { })) &|| Segment::empty().catch_all((comp(Greeting), Name { }))
); );
// ... // ...
cx.render(rsx! { render! {
Outlet { } Outlet { }
}) }
} }
# #
# let mut vdom = VirtualDom::new(App); # let mut vdom = VirtualDom::new(App);

View file

@ -20,21 +20,21 @@ use dioxus_router::{history::MemoryHistory, prelude::*};
# extern crate dioxus_ssr; # extern crate dioxus_ssr;
fn Index(cx: Scope) -> Element { fn Index(cx: Scope) -> Element {
cx.render(rsx! { render! {
h1 { "Index" } h1 { "Index" }
}) }
} }
fn Fallback(cx: Scope) -> Element { fn Fallback(cx: Scope) -> Element {
cx.render(rsx! { render! {
h1 { "Error 404 - Not Found" } h1 { "Error 404 - Not Found" }
p { "The page you asked for doesn't exist." } p { "The page you asked for doesn't exist." }
}) }
} }
fn App(cx: Scope) -> Element { fn App(cx: Scope) -> Element {
use_router( use_router(
&cx, cx,
&|| RouterConfiguration { &|| RouterConfiguration {
# synchronous: true, # synchronous: true,
# history: Box::new(MemoryHistory::with_initial_path("/invalid").unwrap()), # history: Box::new(MemoryHistory::with_initial_path("/invalid").unwrap()),
@ -45,9 +45,9 @@ fn App(cx: Scope) -> Element {
} }
); );
cx.render(rsx! { render! {
Outlet { } Outlet { }
}) }
} }
# #
# let mut vdom = VirtualDom::new(App); # let mut vdom = VirtualDom::new(App);
@ -90,20 +90,20 @@ use dioxus_router::{history::MemoryHistory, prelude::*};
# fn PrivacySettings(cx: Scope) -> Element { unimplemented!() } # fn PrivacySettings(cx: Scope) -> Element { unimplemented!() }
fn GlobalFallback(cx: Scope) -> Element { fn GlobalFallback(cx: Scope) -> Element {
cx.render(rsx! { render! {
h1 { "Error 404 - Page Not Found" } h1 { "Error 404 - Page Not Found" }
}) }
} }
fn SettingsFallback(cx: Scope) -> Element { fn SettingsFallback(cx: Scope) -> Element {
cx.render(rsx! { render! {
h1 { "Error 404 - Settings Not Found" } h1 { "Error 404 - Settings Not Found" }
}) }
} }
fn App(cx: Scope) -> Element { fn App(cx: Scope) -> Element {
use_router( use_router(
&cx, cx,
&|| RouterConfiguration { &|| RouterConfiguration {
# synchronous: true, # synchronous: true,
# history: Box::new(MemoryHistory::with_initial_path("/settings/invalid").unwrap()), # history: Box::new(MemoryHistory::with_initial_path("/settings/invalid").unwrap()),
@ -122,9 +122,9 @@ fn App(cx: Scope) -> Element {
} }
); );
cx.render(rsx! { render! {
Outlet { } Outlet { }
}) }
} }
# #
# let mut vdom = VirtualDom::new(App); # let mut vdom = VirtualDom::new(App);

View file

@ -15,15 +15,15 @@ use dioxus::prelude::*;
use dioxus_router::prelude::*; use dioxus_router::prelude::*;
fn Index(cx: Scope) -> Element { fn Index(cx: Scope) -> Element {
cx.render(rsx! { render! {
h1 { "Welcome to our test site!" } h1 { "Welcome to our test site!" }
}) }
} }
fn Other(cx: Scope) -> Element { fn Other(cx: Scope) -> Element {
cx.render(rsx! { render! {
p { "some other content" } p { "some other content" }
}) }
} }
``` ```
@ -46,7 +46,7 @@ are active, when we don't specify a route.
# #
fn App(cx: Scope) -> Element { fn App(cx: Scope) -> Element {
use_router( use_router(
&cx, cx,
&|| RouterConfiguration { &|| RouterConfiguration {
..Default::default() ..Default::default()
}, },
@ -77,7 +77,7 @@ specified in the path. In the example, the path must be `/other`.
# #
fn App(cx: Scope) -> Element { fn App(cx: Scope) -> Element {
use_router( use_router(
&cx, cx,
&|| RouterConfiguration { &|| RouterConfiguration {
..Default::default() ..Default::default()
}, },
@ -100,20 +100,20 @@ use dioxus_router::{history::MemoryHistory, prelude::*};
# extern crate dioxus_ssr; # extern crate dioxus_ssr;
fn Index(cx: Scope) -> Element { fn Index(cx: Scope) -> Element {
cx.render(rsx! { render! {
h1 { "Welcome to our test site!" } h1 { "Welcome to our test site!" }
}) }
} }
fn Other(cx: Scope) -> Element { fn Other(cx: Scope) -> Element {
cx.render(rsx! { render! {
p { "some other content" } p { "some other content" }
}) }
} }
fn App(cx: Scope) -> Element { fn App(cx: Scope) -> Element {
use_router( use_router(
&cx, cx,
&|| RouterConfiguration { &|| RouterConfiguration {
# synchronous: true, # synchronous: true,
# history: Box::new(MemoryHistory::with_initial_path("/other").unwrap()), # history: Box::new(MemoryHistory::with_initial_path("/other").unwrap()),
@ -122,9 +122,9 @@ fn App(cx: Scope) -> Element {
&|| Segment::content(comp(Index)).fixed("other", comp(Other)) &|| Segment::content(comp(Index)).fixed("other", comp(Other))
); );
cx.render(rsx! { render! {
Outlet { } Outlet { }
}) }
} }
# #
# let mut vdom = VirtualDom::new(App); # let mut vdom = VirtualDom::new(App);

View file

@ -30,7 +30,7 @@ use regex::Regex;
struct Name; struct Name;
fn GreetingFemale(cx: Scope) -> Element { fn GreetingFemale(cx: Scope) -> Element {
let route = use_route(&cx).unwrap(); let route = use_route(cx).unwrap();
let name = route.parameter::<Name>() let name = route.parameter::<Name>()
.map(|name| { .map(|name| {
let mut name = name.to_string(); let mut name = name.to_string();
@ -39,13 +39,13 @@ fn GreetingFemale(cx: Scope) -> Element {
}) })
.unwrap_or(String::from("Anonymous")); .unwrap_or(String::from("Anonymous"));
cx.render(rsx! { render! {
p { "Hello Mrs. {name}" } p { "Hello Mrs. {name}" }
}) }
} }
fn GreetingMale(cx: Scope) -> Element { fn GreetingMale(cx: Scope) -> Element {
let route = use_route(&cx).unwrap(); let route = use_route(cx).unwrap();
let name = route.parameter::<Name>() let name = route.parameter::<Name>()
.map(|name| { .map(|name| {
let mut name = name.to_string(); let mut name = name.to_string();
@ -54,32 +54,32 @@ fn GreetingMale(cx: Scope) -> Element {
}) })
.unwrap_or(String::from("Anonymous")); .unwrap_or(String::from("Anonymous"));
cx.render(rsx! { render! {
p { "Hello Mr. {name}" } p { "Hello Mr. {name}" }
}) }
} }
fn GreetingWithoutGender(cx: Scope) -> Element { fn GreetingWithoutGender(cx: Scope) -> Element {
let route = use_route(&cx).unwrap(); let route = use_route(cx).unwrap();
let name = route.parameter::<Name>() let name = route.parameter::<Name>()
.map(|name| name.to_string()) .map(|name| name.to_string())
.unwrap_or(String::from("Anonymous")); .unwrap_or(String::from("Anonymous"));
cx.render(rsx! { render! {
p { "Hello {name}" } p { "Hello {name}" }
}) }
} }
fn GreetingKenobi(cx: Scope) -> Element { fn GreetingKenobi(cx: Scope) -> Element {
cx.render(rsx! { render! {
p { "Hello there." } p { "Hello there." }
p { "General Kenobi." } p { "General Kenobi." }
}) }
} }
fn App(cx: Scope) -> Element { fn App(cx: Scope) -> Element {
use_router( use_router(
&cx, cx,
&|| RouterConfiguration { &|| RouterConfiguration {
# synchronous: true, # synchronous: true,
# history: Box::new(MemoryHistory::with_initial_path("/fAnna").unwrap()), # history: Box::new(MemoryHistory::with_initial_path("/fAnna").unwrap()),
@ -100,9 +100,9 @@ fn App(cx: Scope) -> Element {
} }
); );
cx.render(rsx! { render! {
Outlet { } Outlet { }
}) }
} }
# #
# let mut vdom = VirtualDom::new(App); # let mut vdom = VirtualDom::new(App);

View file

@ -25,14 +25,14 @@ use dioxus_router::{history::MemoryHistory, prelude::*};
# extern crate dioxus_ssr; # extern crate dioxus_ssr;
fn Home(cx: Scope) -> Element { fn Home(cx: Scope) -> Element {
cx.render(rsx! { render! {
h1 { "Home Page" } h1 { "Home Page" }
}) }
} }
fn App(cx: Scope) -> Element { fn App(cx: Scope) -> Element {
use_router( use_router(
&cx, cx,
&|| RouterConfiguration { &|| RouterConfiguration {
# synchronous: true, # synchronous: true,
# history: Box::new(MemoryHistory::with_initial_path("/home").unwrap()), # history: Box::new(MemoryHistory::with_initial_path("/home").unwrap()),
@ -49,9 +49,9 @@ fn App(cx: Scope) -> Element {
.fixed("start", "/") // short form .fixed("start", "/") // short form
}); });
cx.render(rsx! { render! {
Outlet { } Outlet { }
}) }
} }
# #
# let mut vdom = VirtualDom::new(App); # let mut vdom = VirtualDom::new(App);

View file

@ -48,28 +48,28 @@ the first one, and will in turn render our nested content.
# use dioxus_router::prelude::*; # use dioxus_router::prelude::*;
# #
fn Settings(cx: Scope) -> Element { fn Settings(cx: Scope) -> Element {
cx.render(rsx! { render! {
h1 { "Settings" } h1 { "Settings" }
Outlet { } Outlet { }
}) }
} }
fn GeneralSettings(cx: Scope) -> Element { fn GeneralSettings(cx: Scope) -> Element {
cx.render(rsx! { render! {
h2 { "General Settings" } h2 { "General Settings" }
}) }
} }
fn PWSettings(cx: Scope) -> Element { fn PWSettings(cx: Scope) -> Element {
cx.render(rsx! { render! {
h2 { "Password Settings" } h2 { "Password Settings" }
}) }
} }
fn PrivacySettings(cx: Scope) -> Element { fn PrivacySettings(cx: Scope) -> Element {
cx.render(rsx! { render! {
h2 { "Privacy Settings" } h2 { "Privacy Settings" }
}) }
} }
``` ```
@ -90,7 +90,7 @@ we'll use a method of [`Route`], so we might as well add this now.
# #
fn App(cx: Scope) -> Element { fn App(cx: Scope) -> Element {
use_router( use_router(
&cx, cx,
&|| RouterConfiguration { &|| RouterConfiguration {
..Default::default() ..Default::default()
}, },
@ -123,7 +123,7 @@ pass it to the [`Route`] on the root segment.
# #
fn App(cx: Scope) -> Element { fn App(cx: Scope) -> Element {
use_router( use_router(
&cx, cx,
&|| RouterConfiguration { &|| RouterConfiguration {
..Default::default() ..Default::default()
}, },
@ -152,33 +152,33 @@ fn App(cx: Scope) -> Element {
# extern crate dioxus_ssr; # extern crate dioxus_ssr;
# #
fn Settings(cx: Scope) -> Element { fn Settings(cx: Scope) -> Element {
cx.render(rsx! { render! {
h1 { "Settings" } h1 { "Settings" }
Outlet { } Outlet { }
}) }
} }
fn GeneralSettings(cx: Scope) -> Element { fn GeneralSettings(cx: Scope) -> Element {
cx.render(rsx! { render! {
h2 { "General Settings" } h2 { "General Settings" }
}) }
} }
fn PWSettings(cx: Scope) -> Element { fn PWSettings(cx: Scope) -> Element {
cx.render(rsx! { render! {
h2 { "Password Settings" } h2 { "Password Settings" }
}) }
} }
fn PrivacySettings(cx: Scope) -> Element { fn PrivacySettings(cx: Scope) -> Element {
cx.render(rsx! { render! {
h2 { "Privacy Settings" } h2 { "Privacy Settings" }
}) }
} }
fn App(cx: Scope) -> Element { fn App(cx: Scope) -> Element {
use_router( use_router(
&cx, cx,
&|| RouterConfiguration { &|| RouterConfiguration {
# synchronous: true, # synchronous: true,
# history: Box::new(MemoryHistory::with_initial_path("/settings/privacy").unwrap()), # history: Box::new(MemoryHistory::with_initial_path("/settings/privacy").unwrap()),
@ -194,9 +194,9 @@ fn App(cx: Scope) -> Element {
) )
); );
cx.render(rsx! { render! {
Outlet { } Outlet { }
}) }
} }
# #
# let mut vdom = VirtualDom::new(App); # let mut vdom = VirtualDom::new(App);

View file

@ -32,7 +32,7 @@ use dioxus_router::prelude::*;
fn App(cx: Scope) -> Element { fn App(cx: Scope) -> Element {
use_router( use_router(
&cx, cx,
&|| RouterConfiguration { &|| RouterConfiguration {
# synchronous: true, # synchronous: true,
on_update: Some(Arc::new(|state| -> Option<NavigationTarget> { on_update: Some(Arc::new(|state| -> Option<NavigationTarget> {

View file

@ -15,37 +15,37 @@ use dioxus_router::{history::MemoryHistory, prelude::*};
# extern crate dioxus_ssr; # extern crate dioxus_ssr;
fn Home(cx: Scope) -> Element { fn Home(cx: Scope) -> Element {
cx.render(rsx! { render! {
h1 { "Home" } h1 { "Home" }
}) }
} }
fn Fixed(cx: Scope) -> Element { fn Fixed(cx: Scope) -> Element {
cx.render(rsx! { render! {
h1 { "Fixed" } h1 { "Fixed" }
Outlet { } Outlet { }
}) }
} }
fn Nested(cx: Scope) -> Element { fn Nested(cx: Scope) -> Element {
cx.render(rsx! { render! {
h2 { "Nested" } h2 { "Nested" }
}) }
} }
struct ParameterName; struct ParameterName;
fn Parameter(cx: Scope) -> Element { fn Parameter(cx: Scope) -> Element {
let route = use_route(&cx).unwrap(); let route = use_route(cx).unwrap();
let param = route.parameter::<ParameterName>().unwrap_or_default(); let param = route.parameter::<ParameterName>().unwrap_or_default();
cx.render(rsx! { render! {
h1 { "Parameter: {param}" } h1 { "Parameter: {param}" }
}) }
} }
fn App(cx: Scope) -> Element { fn App(cx: Scope) -> Element {
use_router( use_router(
&cx, cx,
&|| RouterConfiguration { &|| RouterConfiguration {
# synchronous: true, # synchronous: true,
history: Box::new(MemoryHistory::with_initial_path("/fixed/nested").unwrap()), history: Box::new(MemoryHistory::with_initial_path("/fixed/nested").unwrap()),
@ -63,9 +63,9 @@ fn App(cx: Scope) -> Element {
} }
); );
cx.render(rsx! { render! {
Outlet { } Outlet { }
}) }
} }
# #
# let mut vdom = VirtualDom::new(App); # let mut vdom = VirtualDom::new(App);
@ -92,16 +92,16 @@ our segment definition into its own function.
# #
fn App(cx: Scope) -> Element { fn App(cx: Scope) -> Element {
use_router( use_router(
&cx, cx,
&|| RouterConfiguration { &|| RouterConfiguration {
..Default::default() ..Default::default()
}, },
&prepare_routes &prepare_routes
); );
cx.render(rsx! { render! {
Outlet { } Outlet { }
}) }
} }
fn prepare_routes() -> Segment<Component> { fn prepare_routes() -> Segment<Component> {