diff --git a/examples/router.rs b/examples/router.rs index bd6d51881..121514423 100644 --- a/examples/router.rs +++ b/examples/router.rs @@ -2,6 +2,7 @@ use dioxus::prelude::*; use dioxus::router::{Link, Route, Router}; +use serde::Deserialize; fn main() { dioxus::desktop::launch(app); @@ -30,7 +31,7 @@ fn app(cx: Scope) -> Element { } fn BlogPost(cx: Scope) -> Element { - let post = dioxus::router::use_route(&cx).last_segment()?; + let post = dioxus::router::use_route(&cx).last_segment(); cx.render(rsx! { div { @@ -40,9 +41,14 @@ fn BlogPost(cx: Scope) -> Element { }) } +#[derive(Deserialize)] +struct Query { + bold: bool, +} + fn User(cx: Scope) -> Element { - let post = dioxus::router::use_route(&cx).last_segment()?; - let bold = dioxus::router::use_route(&cx).param::("bold"); + let post = dioxus::router::use_route(&cx).last_segment(); + let query = dioxus::router::use_route(&cx).query::(); cx.render(rsx! { div { diff --git a/packages/router/src/hooks/use_route.rs b/packages/router/src/hooks/use_route.rs index 5ed056f65..97dd6c048 100644 --- a/packages/router/src/hooks/use_route.rs +++ b/packages/router/src/hooks/use_route.rs @@ -1,20 +1,29 @@ use dioxus_core::ScopeState; -use gloo::history::Location; +use gloo::history::{HistoryResult, Location}; +use serde::de::DeserializeOwned; use std::{rc::Rc, str::FromStr}; use crate::RouterService; -pub struct UseRoute<'a> { +/// This struct provides is a wrapper around the internal router +/// implementation, with methods for getting information about the current +/// route. +pub struct UseRoute { router: Rc, - cx: &'a ScopeState, } -impl<'a> UseRoute<'a> { - /// Parse the query part of the URL - pub fn param(&self, param: &str) -> Option<&T> { - todo!() +impl UseRoute { + /// This method simply calls the [`Location::query`] method. + pub fn query(&self) -> HistoryResult + where + T: DeserializeOwned, + { + self.current_location().query::() } + /// Returns the nth segment in the path. Paths that end with a slash have + /// the slash removed before determining the segments. If the path has + /// fewer segments than `n` then this method returns `None`. pub fn nth_segment(&self, n: usize) -> Option { let mut segments = self.path_segments(); let len = segments.len(); @@ -24,13 +33,12 @@ impl<'a> UseRoute<'a> { Some(segments.remove(n)) } - pub fn last_segment(&self) -> Option { + /// Returns the last segment in the path. Paths that end with a slash have + /// the slash removed before determining the segments. The root path, `/`, + /// will return an empty string. + pub fn last_segment(&self) -> String { let mut segments = self.path_segments(); - let len = segments.len(); - if len == 0 { - return None; - } - Some(segments.remove(len - 1)) + segments.remove(segments.len() - 1) } /// Get the named parameter from the path, as defined in your router. The @@ -47,21 +55,29 @@ impl<'a> UseRoute<'a> { .and_then(|v| Some(v.parse::())) } + /// Returns the [Location] for the current route. pub fn current_location(&self) -> Location { self.router.current_location() } fn path_segments(&self) -> Vec { let location = self.router.current_location(); + let path = location.path(); + if path == "/" { + return vec![String::new()]; + } let stripped = &location.path()[1..]; stripped.split('/').map(str::to_string).collect::>() } } -pub fn use_route<'a>(cx: &'a ScopeState) -> UseRoute<'a> { +/// This hook provides access to information about the current location in the +/// context of a [`Router`]. If this function is called outside of a `Router` +/// component it will panic. +pub fn use_route(cx: &ScopeState) -> UseRoute { let router = cx .consume_context::() .expect("Cannot call use_route outside the scope of a Router component") .clone(); - UseRoute { router, cx } + UseRoute { router } }