More WIP router implementation

This commit is contained in:
Dave Rolsky 2022-01-11 11:27:02 -06:00
parent c9408da731
commit e06eac1ce5
2 changed files with 40 additions and 18 deletions

View file

@ -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::<bool>("bold");
let post = dioxus::router::use_route(&cx).last_segment();
let query = dioxus::router::use_route(&cx).query::<Query>();
cx.render(rsx! {
div {

View file

@ -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<RouterService>,
cx: &'a ScopeState,
}
impl<'a> UseRoute<'a> {
/// Parse the query part of the URL
pub fn param<T>(&self, param: &str) -> Option<&T> {
todo!()
impl UseRoute {
/// This method simply calls the [`Location::query`] method.
pub fn query<T>(&self) -> HistoryResult<T>
where
T: DeserializeOwned,
{
self.current_location().query::<T>()
}
/// 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<String> {
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<String> {
/// 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::<T>()))
}
/// Returns the [Location] for the current route.
pub fn current_location(&self) -> Location {
self.router.current_location()
}
fn path_segments(&self) -> Vec<String> {
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::<Vec<_>>()
}
}
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::<RouterService>()
.expect("Cannot call use_route outside the scope of a Router component")
.clone();
UseRoute { router, cx }
UseRoute { router }
}