瀏覽代碼

Make deprecated use router (#1260)

* make router props expansion better

* fix router data fields

* make a deprecated use_router hook
ealmloff 1 年之前
父節點
當前提交
cfd62e274e

+ 0 - 4
examples/router.rs

@@ -43,7 +43,6 @@ fn App(cx: Scope) -> Element {
     }
     }
 }
 }
 
 
-#[inline_props]
 fn NavBar(cx: Scope) -> Element {
 fn NavBar(cx: Scope) -> Element {
     render! {
     render! {
         nav {
         nav {
@@ -56,14 +55,12 @@ fn NavBar(cx: Scope) -> Element {
     }
     }
 }
 }
 
 
-#[inline_props]
 fn Home(cx: Scope) -> Element {
 fn Home(cx: Scope) -> Element {
     render! {
     render! {
         h1 { "Welcome to the Dioxus Blog!" }
         h1 { "Welcome to the Dioxus Blog!" }
     }
     }
 }
 }
 
 
-#[inline_props]
 fn Blog(cx: Scope) -> Element {
 fn Blog(cx: Scope) -> Element {
     render! {
     render! {
         h1 { "Blog" }
         h1 { "Blog" }
@@ -71,7 +68,6 @@ fn Blog(cx: Scope) -> Element {
     }
     }
 }
 }
 
 
-#[inline_props]
 fn BlogList(cx: Scope) -> Element {
 fn BlogList(cx: Scope) -> Element {
     render! {
     render! {
         h2 { "Choose a post" }
         h2 { "Choose a post" }

+ 3 - 25
packages/router-macro/src/layout.rs

@@ -1,5 +1,5 @@
 use proc_macro2::TokenStream;
 use proc_macro2::TokenStream;
-use quote::{format_ident, quote};
+use quote::quote;
 use syn::Path;
 use syn::Path;
 
 
 use crate::nest::{Nest, NestId};
 use crate::nest::{Nest, NestId};
@@ -10,25 +10,20 @@ pub struct LayoutId(pub usize);
 #[derive(Debug)]
 #[derive(Debug)]
 pub struct Layout {
 pub struct Layout {
     pub comp: Path,
     pub comp: Path,
-    pub props_name: Path,
     pub active_nests: Vec<NestId>,
     pub active_nests: Vec<NestId>,
 }
 }
 
 
 impl Layout {
 impl Layout {
     pub fn routable_match(&self, nests: &[Nest]) -> TokenStream {
     pub fn routable_match(&self, nests: &[Nest]) -> TokenStream {
-        let props_name = &self.props_name;
         let comp_name = &self.comp;
         let comp_name = &self.comp;
-        let name_str = self.comp.segments.last().unwrap().ident.to_string();
         let dynamic_segments = self
         let dynamic_segments = self
             .active_nests
             .active_nests
             .iter()
             .iter()
             .flat_map(|id| nests[id.0].dynamic_segments());
             .flat_map(|id| nests[id.0].dynamic_segments());
 
 
         quote! {
         quote! {
-            let comp = #props_name { #(#dynamic_segments,)* };
-            let dynamic = cx.component(#comp_name, comp, #name_str);
             render! {
             render! {
-                dynamic
+                #comp_name { #(#dynamic_segments: #dynamic_segments,)* }
             }
             }
         }
         }
     }
     }
@@ -40,23 +35,6 @@ impl Layout {
         let _ = input.parse::<syn::Token![,]>();
         let _ = input.parse::<syn::Token![,]>();
         let comp: Path = input.parse()?;
         let comp: Path = input.parse()?;
 
 
-        // Then parse the props name
-        let _ = input.parse::<syn::Token![,]>();
-        let props_name = input.parse::<Path>().unwrap_or_else(|_| {
-            let last = format_ident!("{}Props", comp.segments.last().unwrap().ident.to_string());
-            let mut segments = comp.segments.clone();
-            segments.pop();
-            segments.push(last.into());
-            Path {
-                leading_colon: None,
-                segments,
-            }
-        });
-
-        Ok(Self {
-            comp,
-            props_name,
-            active_nests,
-        })
+        Ok(Self { comp, active_nests })
     }
     }
 }
 }

+ 11 - 13
packages/router-macro/src/lib.rs

@@ -43,8 +43,8 @@ mod segment;
 /// #[rustfmt::skip]
 /// #[rustfmt::skip]
 /// #[derive(Clone, Debug, PartialEq, Routable)]
 /// #[derive(Clone, Debug, PartialEq, Routable)]
 /// enum Route {
 /// enum Route {
-///     // Define routes with the route macro. If the name of the component is not the same as the variant, you can specify it as the second parameter and the props type as the third
-///     #[route("/", IndexComponent, ComponentProps)]
+///     // Define routes with the route macro. If the name of the component is not the same as the variant, you can specify it as the second parameter
+///     #[route("/", IndexComponent)]
 ///     Index {},
 ///     Index {},
 ///     // Nests with parameters have types taken from child routes
 ///     // Nests with parameters have types taken from child routes
 ///     // Everything inside the nest has the added parameter `user_id: usize`
 ///     // Everything inside the nest has the added parameter `user_id: usize`
@@ -52,7 +52,7 @@ mod segment;
 ///         // All children of layouts will be rendered inside the Outlet in the layout component
 ///         // All children of layouts will be rendered inside the Outlet in the layout component
 ///         // Creates a Layout UserFrame that has the parameter `user_id: usize`
 ///         // Creates a Layout UserFrame that has the parameter `user_id: usize`
 ///         #[layout(UserFrame)]
 ///         #[layout(UserFrame)]
-///             // If there is a component with the name Route1 and props with the name Route1Props, you do not need to pass in the component and type
+///             // If there is a component with the name Route1, you do not need to pass in the component name
 ///             #[route("/:dynamic?:query")]
 ///             #[route("/:dynamic?:query")]
 ///             Route1 {
 ///             Route1 {
 ///                 // The type is taken from the first instance of the dynamic parameter
 ///                 // The type is taken from the first instance of the dynamic parameter
@@ -78,12 +78,11 @@ mod segment;
 /// }
 /// }
 /// ```
 /// ```
 ///
 ///
-/// # `#[route("path", component, props)]`
+/// # `#[route("path", component)]`
 ///
 ///
 /// The `#[route]` attribute is used to define a route. It takes up to 3 parameters:
 /// The `#[route]` attribute is used to define a route. It takes up to 3 parameters:
 /// - `path`: The path to the enum variant (relative to the parent nest)
 /// - `path`: The path to the enum variant (relative to the parent nest)
 /// - (optional) `component`: The component to render when the route is matched. If not specified, the name of the variant is used
 /// - (optional) `component`: The component to render when the route is matched. If not specified, the name of the variant is used
-/// - (optional) `props`: The props type for the component. If not specified, the name of the variant with `Props` appended is used
 ///
 ///
 /// Routes are the most basic attribute. They allow you to define a route and the component to render when the route is matched. The component must take all dynamic parameters of the route and all parent nests.
 /// Routes are the most basic attribute. They allow you to define a route and the component to render when the route is matched. The component must take all dynamic parameters of the route and all parent nests.
 /// The next variant will be tied to the component. If you link to that variant, the component will be rendered.
 /// The next variant will be tied to the component. If you link to that variant, the component will be rendered.
@@ -91,9 +90,9 @@ mod segment;
 /// ```rust, skip
 /// ```rust, skip
 /// #[derive(Clone, Debug, PartialEq, Routable)]
 /// #[derive(Clone, Debug, PartialEq, Routable)]
 /// enum Route {
 /// enum Route {
-///     // Define routes that renders the IndexComponent that takes the IndexProps
+///     // Define routes that renders the IndexComponent
 ///     // The Index component will be rendered when the route is matched (e.g. when the user navigates to /)
 ///     // The Index component will be rendered when the route is matched (e.g. when the user navigates to /)
-///     #[route("/", Index, IndexProps)]
+///     #[route("/", Index)]
 ///     Index {},
 ///     Index {},
 /// }
 /// }
 /// ```
 /// ```
@@ -109,7 +108,7 @@ mod segment;
 /// enum Route {
 /// enum Route {
 ///     // Redirects the /:id route to the Index route
 ///     // Redirects the /:id route to the Index route
 ///     #[redirect("/:id", |_: usize| Route::Index {})]
 ///     #[redirect("/:id", |_: usize| Route::Index {})]
-///     #[route("/", Index, IndexProps)]
+///     #[route("/", Index)]
 ///     Index {},
 ///     Index {},
 /// }
 /// }
 /// ```
 /// ```
@@ -131,7 +130,7 @@ mod segment;
 ///         // This is at /blog/:id
 ///         // This is at /blog/:id
 ///         #[redirect("/:id", |_: usize| Route::Index {})]
 ///         #[redirect("/:id", |_: usize| Route::Index {})]
 ///         // This is at /blog
 ///         // This is at /blog
-///         #[route("/", Index, IndexProps)]
+///         #[route("/", Index)]
 ///         Index {},
 ///         Index {},
 /// }
 /// }
 /// ```
 /// ```
@@ -147,7 +146,7 @@ mod segment;
 ///         // This is at /blog/:id
 ///         // This is at /blog/:id
 ///         #[redirect("/:id", |_: usize| Route::Index {})]
 ///         #[redirect("/:id", |_: usize| Route::Index {})]
 ///         // This is at /blog
 ///         // This is at /blog
-///         #[route("/", Index, IndexProps)]
+///         #[route("/", Index)]
 ///         Index {},
 ///         Index {},
 ///     // Ends the nest
 ///     // Ends the nest
 ///     #[end_nest]
 ///     #[end_nest]
@@ -161,7 +160,6 @@ mod segment;
 ///
 ///
 /// The `#[layout]` attribute is used to define a layout. It takes 2 parameters:
 /// The `#[layout]` attribute is used to define a layout. It takes 2 parameters:
 /// - `component`: The component to render when the route is matched. If not specified, the name of the variant is used
 /// - `component`: The component to render when the route is matched. If not specified, the name of the variant is used
-/// - (optional) `props`: The props type for the component. If not specified, the name of the variant with `Props` appended is used
 ///
 ///
 /// The layout component allows you to wrap all children of the layout in a component. The child routes are rendered in the Outlet of the layout component. The layout component must take all dynamic parameters of the nests it is nested in.
 /// The layout component allows you to wrap all children of the layout in a component. The child routes are rendered in the Outlet of the layout component. The layout component must take all dynamic parameters of the nests it is nested in.
 ///
 ///
@@ -171,7 +169,7 @@ mod segment;
 ///     #[layout(BlogFrame)]
 ///     #[layout(BlogFrame)]
 ///         #[redirect("/:id", |_: usize| Route::Index {})]
 ///         #[redirect("/:id", |_: usize| Route::Index {})]
 ///         // Index will be rendered in the Outlet of the BlogFrame component
 ///         // Index will be rendered in the Outlet of the BlogFrame component
-///         #[route("/", Index, IndexProps)]
+///         #[route("/", Index)]
 ///         Index {},
 ///         Index {},
 /// }
 /// }
 /// ```
 /// ```
@@ -186,7 +184,7 @@ mod segment;
 ///     #[layout(BlogFrame)]
 ///     #[layout(BlogFrame)]
 ///         #[redirect("/:id", |_: usize| Route::Index {})]
 ///         #[redirect("/:id", |_: usize| Route::Index {})]
 ///         // Index will be rendered in the Outlet of the BlogFrame component
 ///         // Index will be rendered in the Outlet of the BlogFrame component
-///         #[route("/", Index, IndexProps)]
+///         #[route("/", Index)]
 ///         Index {},
 ///         Index {},
 ///     // Ends the layout
 ///     // Ends the layout
 ///     #[end_layout]
 ///     #[end_layout]

+ 5 - 25
packages/router-macro/src/route.rs

@@ -21,7 +21,6 @@ use crate::segment::RouteSegment;
 struct RouteArgs {
 struct RouteArgs {
     route: LitStr,
     route: LitStr,
     comp_name: Option<Path>,
     comp_name: Option<Path>,
-    props_name: Option<Path>,
 }
 }
 
 
 impl Parse for RouteArgs {
 impl Parse for RouteArgs {
@@ -34,10 +33,6 @@ impl Parse for RouteArgs {
                 let _ = input.parse::<syn::Token![,]>();
                 let _ = input.parse::<syn::Token![,]>();
                 input.parse().ok()
                 input.parse().ok()
             },
             },
-            props_name: {
-                let _ = input.parse::<syn::Token![,]>();
-                input.parse().ok()
-            },
         })
         })
     }
     }
 }
 }
@@ -83,22 +78,8 @@ impl Route {
             Some(attr) => {
             Some(attr) => {
                 let args = attr.parse_args::<RouteArgs>()?;
                 let args = attr.parse_args::<RouteArgs>()?;
                 let comp_name = args.comp_name.unwrap_or_else(|| parse_quote!(#route_name));
                 let comp_name = args.comp_name.unwrap_or_else(|| parse_quote!(#route_name));
-                let props_name = args.props_name.unwrap_or_else(|| {
-                    let last = format_ident!(
-                        "{}Props",
-                        comp_name.segments.last().unwrap().ident.to_string()
-                    );
-                    let mut segments = comp_name.segments.clone();
-                    segments.pop();
-                    segments.push(last.into());
-                    Path {
-                        leading_colon: None,
-                        segments,
-                    }
-                });
                 ty = RouteType::Leaf {
                 ty = RouteType::Leaf {
                     component: comp_name,
                     component: comp_name,
-                    props: props_name,
                 };
                 };
                 route = args.route.value();
                 route = args.route.value();
             }
             }
@@ -227,7 +208,6 @@ impl Route {
 
 
     pub fn routable_match(&self, layouts: &[Layout], nests: &[Nest]) -> TokenStream2 {
     pub fn routable_match(&self, layouts: &[Layout], nests: &[Nest]) -> TokenStream2 {
         let name = &self.route_name;
         let name = &self.route_name;
-        let name_str = name.to_string();
 
 
         let mut tokens = TokenStream2::new();
         let mut tokens = TokenStream2::new();
 
 
@@ -261,16 +241,16 @@ impl Route {
                     }
                     }
                 }
                 }
             }
             }
-            RouteType::Leaf { component, props } => {
+            RouteType::Leaf { component } => {
                 let dynamic_segments = self.dynamic_segments();
                 let dynamic_segments = self.dynamic_segments();
                 let dynamic_segments_from_route = self.dynamic_segments();
                 let dynamic_segments_from_route = self.dynamic_segments();
                 quote! {
                 quote! {
                     #[allow(unused)]
                     #[allow(unused)]
                     (#last_index, Self::#name { #(#dynamic_segments,)* }) => {
                     (#last_index, Self::#name { #(#dynamic_segments,)* }) => {
-                        let comp = #props { #(#dynamic_segments_from_route,)* };
-                        let dynamic = cx.component(#component, comp, #name_str);
                         render! {
                         render! {
-                            dynamic
+                            #component {
+                                #(#dynamic_segments_from_route: #dynamic_segments_from_route,)*
+                            }
                         }
                         }
                     }
                     }
                 }
                 }
@@ -364,5 +344,5 @@ impl Route {
 #[derive(Debug)]
 #[derive(Debug)]
 pub(crate) enum RouteType {
 pub(crate) enum RouteType {
     Child(Field),
     Child(Field),
-    Leaf { component: Path, props: Path },
+    Leaf { component: Path },
 }
 }

+ 2 - 0
packages/router/src/components/default_errors.rs

@@ -1,9 +1,11 @@
+#[allow(deprecated)]
 use crate::hooks::use_router;
 use crate::hooks::use_router;
 use dioxus::prelude::*;
 use dioxus::prelude::*;
 
 
 /// The default component to render when an external navigation fails.
 /// The default component to render when an external navigation fails.
 #[allow(non_snake_case)]
 #[allow(non_snake_case)]
 pub fn FailureExternalNavigation(cx: Scope) -> Element {
 pub fn FailureExternalNavigation(cx: Scope) -> Element {
+    #[allow(deprecated)]
     let router = use_router(cx);
     let router = use_router(cx);
 
 
     render! {
     render! {

+ 7 - 10
packages/router/src/components/link.rs

@@ -1,5 +1,6 @@
 use std::any::Any;
 use std::any::Any;
 use std::fmt::Debug;
 use std::fmt::Debug;
+use std::rc::Rc;
 
 
 use dioxus::prelude::*;
 use dioxus::prelude::*;
 use log::error;
 use log::error;
@@ -9,25 +10,24 @@ use crate::prelude::Routable;
 use crate::utils::use_router_internal::use_router_internal;
 use crate::utils::use_router_internal::use_router_internal;
 
 
 /// Something that can be converted into a [`NavigationTarget`].
 /// Something that can be converted into a [`NavigationTarget`].
+#[derive(Clone)]
 pub enum IntoRoutable {
 pub enum IntoRoutable {
     /// A raw string target.
     /// A raw string target.
     FromStr(String),
     FromStr(String),
     /// A internal target.
     /// A internal target.
-    Route(Box<dyn Any>),
+    Route(Rc<dyn Any>),
 }
 }
 
 
 impl<R: Routable> From<R> for IntoRoutable {
 impl<R: Routable> From<R> for IntoRoutable {
     fn from(value: R) -> Self {
     fn from(value: R) -> Self {
-        IntoRoutable::Route(Box::new(value) as Box<dyn Any>)
+        IntoRoutable::Route(Rc::new(value) as Rc<dyn Any>)
     }
     }
 }
 }
 
 
 impl<R: Routable> From<NavigationTarget<R>> for IntoRoutable {
 impl<R: Routable> From<NavigationTarget<R>> for IntoRoutable {
     fn from(value: NavigationTarget<R>) -> Self {
     fn from(value: NavigationTarget<R>) -> Self {
         match value {
         match value {
-            NavigationTarget::Internal(route) => {
-                IntoRoutable::Route(Box::new(route) as Box<dyn Any>)
-            }
+            NavigationTarget::Internal(route) => IntoRoutable::Route(Rc::new(route) as Rc<dyn Any>),
             NavigationTarget::External(url) => IntoRoutable::FromStr(url),
             NavigationTarget::External(url) => IntoRoutable::FromStr(url),
         }
         }
     }
     }
@@ -197,10 +197,7 @@ pub fn Link<'a>(cx: Scope<'a, LinkProps<'a>>) -> Element {
         IntoRoutable::FromStr(url) => url.to_string(),
         IntoRoutable::FromStr(url) => url.to_string(),
         IntoRoutable::Route(route) => router.any_route_to_string(&**route),
         IntoRoutable::Route(route) => router.any_route_to_string(&**route),
     };
     };
-    let parsed_route: NavigationTarget<Box<dyn Any>> = match router.route_from_str(&href) {
-        Ok(route) => NavigationTarget::Internal(route),
-        Err(err) => NavigationTarget::External(err),
-    };
+    let parsed_route: NavigationTarget<Rc<dyn Any>> = router.resolve_into_routable(to.clone());
     let ac = active_class
     let ac = active_class
         .and_then(|active_class| (href == current_url).then(|| format!(" {active_class}")))
         .and_then(|active_class| (href == current_url).then(|| format!(" {active_class}")))
         .unwrap_or_default();
         .unwrap_or_default();
@@ -219,7 +216,7 @@ pub fn Link<'a>(cx: Scope<'a, LinkProps<'a>>) -> Element {
     let do_default = onclick.is_none() || !onclick_only;
     let do_default = onclick.is_none() || !onclick_only;
     let action = move |event| {
     let action = move |event| {
         if do_default && is_router_nav {
         if do_default && is_router_nav {
-            router.push_any(router.resolve_into_routable(to));
+            router.push_any(router.resolve_into_routable(to.clone()));
         }
         }
 
 
         if let Some(handler) = onclick {
         if let Some(handler) = onclick {

+ 2 - 6
packages/router/src/contexts/navigator.rs

@@ -35,17 +35,13 @@ impl Navigator {
     ///
     ///
     /// The previous location will be available to go back to.
     /// The previous location will be available to go back to.
     pub fn push(&self, target: impl Into<IntoRoutable>) -> Option<ExternalNavigationFailure> {
     pub fn push(&self, target: impl Into<IntoRoutable>) -> Option<ExternalNavigationFailure> {
-        let target = target.into();
-        let as_any_navigation_target = self.0.resolve_into_routable(&target);
-        self.0.push_any(as_any_navigation_target)
+        self.0.push(target)
     }
     }
 
 
     /// Replace the current location.
     /// Replace the current location.
     ///
     ///
     /// The previous location will **not** be available to go back to.
     /// The previous location will **not** be available to go back to.
     pub fn replace(&self, target: impl Into<IntoRoutable>) -> Option<ExternalNavigationFailure> {
     pub fn replace(&self, target: impl Into<IntoRoutable>) -> Option<ExternalNavigationFailure> {
-        let target = target.into();
-        let as_any_navigation_target = self.0.resolve_into_routable(&target);
-        self.0.replace_any(as_any_navigation_target)
+        self.0.replace(target)
     }
     }
 }
 }

+ 34 - 51
packages/router/src/contexts/router.rs

@@ -1,6 +1,7 @@
 use std::{
 use std::{
     any::Any,
     any::Any,
     collections::HashSet,
     collections::HashSet,
+    rc::Rc,
     sync::{Arc, RwLock, RwLockWriteGuard},
     sync::{Arc, RwLock, RwLockWriteGuard},
 };
 };
 
 
@@ -18,9 +19,10 @@ use crate::{
 pub struct ExternalNavigationFailure(String);
 pub struct ExternalNavigationFailure(String);
 
 
 /// A function the router will call after every routing update.
 /// A function the router will call after every routing update.
-pub(crate) type RoutingCallback<R> = Arc<dyn Fn(LinkContext<R>) -> Option<NavigationTarget<R>>>;
+pub(crate) type RoutingCallback<R> =
+    Arc<dyn Fn(GenericRouterContext<R>) -> Option<NavigationTarget<R>>>;
 pub(crate) type AnyRoutingCallback =
 pub(crate) type AnyRoutingCallback =
-    Arc<dyn Fn(RouterContext) -> Option<NavigationTarget<Box<dyn Any>>>>;
+    Arc<dyn Fn(RouterContext) -> Option<NavigationTarget<Rc<dyn Any>>>>;
 
 
 struct MutableRouterState {
 struct MutableRouterState {
     /// The current prefix.
     /// The current prefix.
@@ -70,18 +72,18 @@ impl RouterContext {
 
 
             routing_callback: cfg.on_update.map(|update| {
             routing_callback: cfg.on_update.map(|update| {
                 Arc::new(move |ctx| {
                 Arc::new(move |ctx| {
-                    let ctx = LinkContext {
+                    let ctx = GenericRouterContext {
                         inner: ctx,
                         inner: ctx,
                         _marker: std::marker::PhantomData,
                         _marker: std::marker::PhantomData,
                     };
                     };
                     update(ctx).map(|t| match t {
                     update(ctx).map(|t| match t {
                         NavigationTarget::Internal(r) => {
                         NavigationTarget::Internal(r) => {
-                            NavigationTarget::Internal(Box::new(r) as Box<dyn Any>)
+                            NavigationTarget::Internal(Rc::new(r) as Rc<dyn Any>)
                         }
                         }
                         NavigationTarget::External(s) => NavigationTarget::External(s),
                         NavigationTarget::External(s) => NavigationTarget::External(s),
                     })
                     })
                 })
                 })
-                    as Arc<dyn Fn(RouterContext) -> Option<NavigationTarget<Box<dyn Any>>>>
+                    as Arc<dyn Fn(RouterContext) -> Option<NavigationTarget<Rc<dyn Any>>>>
             }),
             }),
 
 
             failure_external_navigation: cfg.failure_external_navigation,
             failure_external_navigation: cfg.failure_external_navigation,
@@ -114,7 +116,7 @@ impl RouterContext {
         myself
         myself
     }
     }
 
 
-    pub(crate) fn route_from_str(&self, route: &str) -> Result<Box<dyn Any>, String> {
+    pub(crate) fn route_from_str(&self, route: &str) -> Result<Rc<dyn Any>, String> {
         let state = self.state.read().unwrap();
         let state = self.state.read().unwrap();
         state.history.parse_route(route)
         state.history.parse_route(route)
     }
     }
@@ -155,7 +157,7 @@ impl RouterContext {
 
 
     pub(crate) fn push_any(
     pub(crate) fn push_any(
         &self,
         &self,
-        target: NavigationTarget<Box<dyn Any>>,
+        target: NavigationTarget<Rc<dyn Any>>,
     ) -> Option<ExternalNavigationFailure> {
     ) -> Option<ExternalNavigationFailure> {
         match target {
         match target {
             NavigationTarget::Internal(p) => {
             NavigationTarget::Internal(p) => {
@@ -171,15 +173,12 @@ impl RouterContext {
     /// Push a new location.
     /// Push a new location.
     ///
     ///
     /// The previous location will be available to go back to.
     /// The previous location will be available to go back to.
-    pub fn push<R: Routable>(
-        &self,
-        target: impl Into<NavigationTarget<R>>,
-    ) -> Option<ExternalNavigationFailure> {
-        let target = target.into();
+    pub fn push(&self, target: impl Into<IntoRoutable>) -> Option<ExternalNavigationFailure> {
+        let target = self.resolve_into_routable(target.into());
         match target {
         match target {
             NavigationTarget::Internal(p) => {
             NavigationTarget::Internal(p) => {
                 let mut state = self.state_mut();
                 let mut state = self.state_mut();
-                state.history.push(Box::new(p))
+                state.history.push(Rc::new(p))
             }
             }
             NavigationTarget::External(e) => return self.external(e),
             NavigationTarget::External(e) => return self.external(e),
         }
         }
@@ -190,16 +189,13 @@ impl RouterContext {
     /// Replace the current location.
     /// Replace the current location.
     ///
     ///
     /// The previous location will **not** be available to go back to.
     /// The previous location will **not** be available to go back to.
-    pub fn replace<R: Routable>(
-        &self,
-        target: impl Into<NavigationTarget<R>>,
-    ) -> Option<ExternalNavigationFailure> {
-        let target = target.into();
+    pub fn replace(&self, target: impl Into<IntoRoutable>) -> Option<ExternalNavigationFailure> {
+        let target = self.resolve_into_routable(target.into());
 
 
         {
         {
             let mut state = self.state_mut();
             let mut state = self.state_mut();
             match target {
             match target {
-                NavigationTarget::Internal(p) => state.history.replace(Box::new(p)),
+                NavigationTarget::Internal(p) => state.history.replace(Rc::new(p)),
                 NavigationTarget::External(e) => return self.external(e),
                 NavigationTarget::External(e) => return self.external(e),
             }
             }
         }
         }
@@ -207,31 +203,17 @@ impl RouterContext {
         self.change_route()
         self.change_route()
     }
     }
 
 
-    pub(crate) fn replace_any(
-        &self,
-        target: NavigationTarget<Box<dyn Any>>,
-    ) -> Option<ExternalNavigationFailure> {
-        match target {
-            NavigationTarget::Internal(p) => {
-                let mut state = self.state_mut();
-                state.history.replace(p)
-            }
-            NavigationTarget::External(e) => return self.external(e),
-        }
-
-        self.change_route()
-    }
-
     /// The route that is currently active.
     /// The route that is currently active.
     pub fn current<R: Routable>(&self) -> R {
     pub fn current<R: Routable>(&self) -> R {
-        *self
-            .state
+        self.state
             .read()
             .read()
             .unwrap()
             .unwrap()
             .history
             .history
             .current_route()
             .current_route()
             .downcast::<R>()
             .downcast::<R>()
             .unwrap()
             .unwrap()
+            .as_ref()
+            .clone()
     }
     }
 
 
     /// The route that is currently active.
     /// The route that is currently active.
@@ -245,17 +227,18 @@ impl RouterContext {
 
 
     pub(crate) fn resolve_into_routable(
     pub(crate) fn resolve_into_routable(
         &self,
         &self,
-        into_routable: &IntoRoutable,
-    ) -> NavigationTarget<Box<dyn Any>> {
-        let href = match into_routable {
-            IntoRoutable::FromStr(url) => url.to_string(),
-            IntoRoutable::Route(route) => self.any_route_to_string(&**route),
-        };
-        let parsed_route: NavigationTarget<Box<dyn Any>> = match self.route_from_str(&href) {
-            Ok(route) => NavigationTarget::Internal(route),
-            Err(err) => NavigationTarget::External(err),
-        };
-        parsed_route
+        into_routable: IntoRoutable,
+    ) -> NavigationTarget<Rc<dyn Any>> {
+        match into_routable {
+            IntoRoutable::FromStr(url) => {
+                let parsed_route: NavigationTarget<Rc<dyn Any>> = match self.route_from_str(&url) {
+                    Ok(route) => NavigationTarget::Internal(route),
+                    Err(err) => NavigationTarget::External(err),
+                };
+                parsed_route
+            }
+            IntoRoutable::Route(route) => NavigationTarget::Internal(route),
+        }
     }
     }
 
 
     /// The prefix that is currently active.
     /// The prefix that is currently active.
@@ -332,12 +315,12 @@ impl RouterContext {
     }
     }
 }
 }
 
 
-pub struct LinkContext<R> {
+pub struct GenericRouterContext<R> {
     inner: RouterContext,
     inner: RouterContext,
     _marker: std::marker::PhantomData<R>,
     _marker: std::marker::PhantomData<R>,
 }
 }
 
 
-impl<R> LinkContext<R>
+impl<R> GenericRouterContext<R>
 where
 where
     R: Routable,
     R: Routable,
 {
 {
@@ -374,7 +357,7 @@ where
         &self,
         &self,
         target: impl Into<NavigationTarget<R>>,
         target: impl Into<NavigationTarget<R>>,
     ) -> Option<ExternalNavigationFailure> {
     ) -> Option<ExternalNavigationFailure> {
-        self.inner.push(target)
+        self.inner.push(target.into())
     }
     }
 
 
     /// Replace the current location.
     /// Replace the current location.
@@ -384,7 +367,7 @@ where
         &self,
         &self,
         target: impl Into<NavigationTarget<R>>,
         target: impl Into<NavigationTarget<R>>,
     ) -> Option<ExternalNavigationFailure> {
     ) -> Option<ExternalNavigationFailure> {
-        self.inner.replace(target)
+        self.inner.replace(target.into())
     }
     }
 
 
     /// The route that is currently active.
     /// The route that is currently active.

+ 15 - 13
packages/router/src/history/mod.rs

@@ -10,7 +10,7 @@
 //! 1) [`MemoryHistory`] for desktop/mobile/ssr platforms
 //! 1) [`MemoryHistory`] for desktop/mobile/ssr platforms
 //! 2) [`WebHistory`] for web platforms
 //! 2) [`WebHistory`] for web platforms
 
 
-use std::{any::Any, sync::Arc};
+use std::{any::Any, rc::Rc, sync::Arc};
 
 
 mod memory;
 mod memory;
 pub use memory::*;
 pub use memory::*;
@@ -279,13 +279,13 @@ pub trait HistoryProvider<R: Routable> {
 }
 }
 
 
 pub(crate) trait AnyHistoryProvider {
 pub(crate) trait AnyHistoryProvider {
-    fn parse_route(&self, route: &str) -> Result<Box<dyn Any>, String>;
+    fn parse_route(&self, route: &str) -> Result<Rc<dyn Any>, String>;
 
 
     #[must_use]
     #[must_use]
     fn accepts_type_id(&self, type_id: &std::any::TypeId) -> bool;
     fn accepts_type_id(&self, type_id: &std::any::TypeId) -> bool;
 
 
     #[must_use]
     #[must_use]
-    fn current_route(&self) -> Box<dyn Any>;
+    fn current_route(&self) -> Rc<dyn Any>;
 
 
     #[must_use]
     #[must_use]
     fn current_prefix(&self) -> Option<String> {
     fn current_prefix(&self) -> Option<String> {
@@ -306,9 +306,9 @@ pub(crate) trait AnyHistoryProvider {
 
 
     fn go_forward(&mut self);
     fn go_forward(&mut self);
 
 
-    fn push(&mut self, route: Box<dyn Any>);
+    fn push(&mut self, route: Rc<dyn Any>);
 
 
-    fn replace(&mut self, path: Box<dyn Any>);
+    fn replace(&mut self, path: Rc<dyn Any>);
 
 
     #[allow(unused_variables)]
     #[allow(unused_variables)]
     fn external(&mut self, url: String) -> bool {
     fn external(&mut self, url: String) -> bool {
@@ -345,19 +345,19 @@ where
     <R as std::str::FromStr>::Err: std::fmt::Display,
     <R as std::str::FromStr>::Err: std::fmt::Display,
     H: HistoryProvider<R>,
     H: HistoryProvider<R>,
 {
 {
-    fn parse_route(&self, route: &str) -> Result<Box<dyn Any>, String> {
+    fn parse_route(&self, route: &str) -> Result<Rc<dyn Any>, String> {
         R::from_str(route)
         R::from_str(route)
             .map_err(|err| err.to_string())
             .map_err(|err| err.to_string())
-            .map(|route| Box::new(route) as Box<dyn Any>)
+            .map(|route| Rc::new(route) as Rc<dyn Any>)
     }
     }
 
 
     fn accepts_type_id(&self, type_id: &std::any::TypeId) -> bool {
     fn accepts_type_id(&self, type_id: &std::any::TypeId) -> bool {
         type_id == &std::any::TypeId::of::<R>()
         type_id == &std::any::TypeId::of::<R>()
     }
     }
 
 
-    fn current_route(&self) -> Box<dyn Any> {
+    fn current_route(&self) -> Rc<dyn Any> {
         let route = self.inner.current_route();
         let route = self.inner.current_route();
-        Box::new(route)
+        Rc::new(route)
     }
     }
 
 
     fn current_prefix(&self) -> Option<String> {
     fn current_prefix(&self) -> Option<String> {
@@ -380,12 +380,14 @@ where
         self.inner.go_forward()
         self.inner.go_forward()
     }
     }
 
 
-    fn push(&mut self, route: Box<dyn Any>) {
-        self.inner.push(*route.downcast().unwrap())
+    fn push(&mut self, route: Rc<dyn Any>) {
+        self.inner
+            .push(route.downcast::<R>().unwrap().as_ref().clone())
     }
     }
 
 
-    fn replace(&mut self, path: Box<dyn Any>) {
-        self.inner.replace(*path.downcast().unwrap())
+    fn replace(&mut self, route: Rc<dyn Any>) {
+        self.inner
+            .replace(route.downcast::<R>().unwrap().as_ref().clone())
     }
     }
 
 
     fn external(&mut self, url: String) -> bool {
     fn external(&mut self, url: String) -> bool {

+ 1 - 0
packages/router/src/hooks/use_router.rs

@@ -2,6 +2,7 @@ use dioxus::prelude::ScopeState;
 
 
 use crate::{prelude::RouterContext, utils::use_router_internal::use_router_internal};
 use crate::{prelude::RouterContext, utils::use_router_internal::use_router_internal};
 
 
+#[deprecated = "prefer the use_navigator or use_route functions"]
 /// A hook that provides access to information about the router.
 /// A hook that provides access to information about the router.
 pub fn use_router(cx: &ScopeState) -> &RouterContext {
 pub fn use_router(cx: &ScopeState) -> &RouterContext {
     use_router_internal(cx)
     use_router_internal(cx)

+ 1 - 1
packages/router/src/lib.rs

@@ -42,7 +42,7 @@ mod history;
 /// Hooks for interacting with the router in components.
 /// Hooks for interacting with the router in components.
 pub mod hooks {
 pub mod hooks {
     mod use_router;
     mod use_router;
-    pub(crate) use use_router::*;
+    pub use use_router::*;
 
 
     mod use_route;
     mod use_route;
     pub use use_route::*;
     pub use use_route::*;

+ 1 - 1
packages/router/src/router_cfg.rs

@@ -112,7 +112,7 @@ where
     /// Defaults to [`None`].
     /// Defaults to [`None`].
     pub fn on_update(
     pub fn on_update(
         self,
         self,
-        callback: impl Fn(LinkContext<R>) -> Option<NavigationTarget<R>> + 'static,
+        callback: impl Fn(GenericRouterContext<R>) -> Option<NavigationTarget<R>> + 'static,
     ) -> Self {
     ) -> Self {
         Self {
         Self {
             on_update: Some(Arc::new(callback)),
             on_update: Some(Arc::new(callback)),