瀏覽代碼

create non generic wrappers for each route

Evan Almloff 2 年之前
父節點
當前提交
d3b21879fb

+ 21 - 0
packages/router-macro/src/lib.rs

@@ -32,8 +32,26 @@ pub fn routable(input: TokenStream) -> TokenStream {
     let parse_impl = route_enum.parse_impl();
     let display_impl = route_enum.impl_display();
     let routable_impl = route_enum.routable_impl();
+    let name = &route_enum.name;
+    let vis = &route_enum.vis;
 
     quote! {
+        #vis fn Outlet(cx: dioxus::prelude::Scope) -> dioxus::prelude::Element {
+            dioxus_router::prelude::GenericOutlet::<#name>(cx)
+        }
+
+        #vis fn Router(cx: dioxus::prelude::Scope<dioxus_router::prelude::GenericRouterProps<#name>>) -> dioxus::prelude::Element {
+            dioxus_router::prelude::GenericRouter(cx)
+        }
+
+        #vis fn Link<'a>(cx: dioxus::prelude::Scope<'a, dioxus_router::prelude::GenericLinkProps<'a, #name>>) -> dioxus::prelude::Element<'a> {
+            dioxus_router::prelude::GenericLink(cx)
+        }
+
+        #vis fn use_router<R: dioxus_router::prelude::Routable + Clone>(cx: &dioxus::prelude::ScopeState) -> &dioxus_router::prelude::GenericRouterContext<R> {
+            dioxus_router::prelude::use_generic_router::<R>(cx)
+        }
+
         #route_enum
 
         #error_type
@@ -48,6 +66,7 @@ pub fn routable(input: TokenStream) -> TokenStream {
 }
 
 struct RouteEnum {
+    vis: syn::Visibility,
     name: Ident,
     routes: Vec<Route>,
     nests: Vec<Nest>,
@@ -58,6 +77,7 @@ struct RouteEnum {
 impl RouteEnum {
     fn parse(data: syn::ItemEnum) -> syn::Result<Self> {
         let name = &data.ident;
+        let vis = &data.vis;
 
         let mut site_map = Vec::new();
         let mut site_map_stack: Vec<Vec<SiteMapSegment>> = Vec::new();
@@ -201,6 +221,7 @@ impl RouteEnum {
         }
 
         let myself = Self {
+            vis: vis.clone(),
             name: name.clone(),
             routes,
             nests,

+ 7 - 7
packages/router/examples/simple_routes.rs

@@ -15,7 +15,7 @@ fn main() {
 
 fn root(cx: Scope) -> Element {
     render! {
-        Router::<Route> {
+        Router {
             config: RouterConfiguration {
                 history: {
                     #[cfg(not(target_arch = "wasm32"))]
@@ -39,7 +39,7 @@ fn UserFrame(cx: Scope, user_id: usize) -> Element {
         div {
             background_color: "rgba(0,0,0,50%)",
             "children:"
-            Outlet::<Route> {}
+            Outlet {}
         }
     }
 }
@@ -50,12 +50,12 @@ fn Route1(cx: Scope, user_id: usize, dynamic: usize, extra: String) -> Element {
         pre {
             "Route1{{\n\tuser_id:{user_id},\n\tdynamic:{dynamic},\n\textra:{extra}\n}}"
         }
-        Link::<Route> {
+        Link {
             target: Route::Route1 { user_id: *user_id, dynamic: *dynamic, extra: extra.clone() + "." },
             "Route1 with extra+\".\""
         }
         p { "Footer" }
-        Link::<Route> {
+        Link {
             target: Route::Route3 { dynamic: String::new() },
             "Home"
         }
@@ -70,7 +70,7 @@ fn Route2(cx: Scope, user_id: usize) -> Element {
         }
         (0..*user_id).map(|i| rsx!{ p { "{i}" } }),
         p { "Footer" }
-        Link::<Route> {
+        Link {
             target: Route::Route3 { dynamic: String::new() },
             "Home"
         }
@@ -97,7 +97,7 @@ fn Route3(cx: Scope, dynamic: String) -> Element {
             value: "{current_route.read()}"
         }
         "dynamic: {dynamic}"
-        Link::<Route> {
+        Link {
             target: Route::Route2 { user_id: 8888 },
             "hello world link"
         }
@@ -107,7 +107,7 @@ fn Route3(cx: Scope, dynamic: String) -> Element {
         if let Ok(route) = parsed {
             if route != router_route {
                 render! {
-                    Link::<Route> {
+                    Link {
                         target: route.clone(),
                         "{route}"
                     }

+ 5 - 3
packages/router/src/components/default_errors.rs

@@ -1,4 +1,6 @@
-use crate::{components::Link, hooks::use_route, navigation::NavigationTarget, routable::Routable};
+use crate::{
+    components::GenericLink, hooks::use_route, navigation::NavigationTarget, routable::Routable,
+};
 use dioxus::prelude::*;
 
 #[allow(non_snake_case)]
@@ -35,7 +37,7 @@ pub fn FailureNamedNavigation<R: Routable + Clone>(cx: Scope) -> Element {
             "We are sorry for the inconvenience. The link below may help to fix the problem, but "
             "there is no guarantee."
         }
-        Link::<R> {
+        GenericLink::<R> {
             target: NavigationTarget::External("https://google.com".into()),
             "Click here to try to fix the failure."
         }
@@ -55,7 +57,7 @@ pub fn FailureRedirectionLimit<R: Routable + Clone>(cx: Scope) -> Element {
             "We are sorry for the inconvenience. The link below may help to fix the problem, but "
             "there is no guarantee."
         }
-        Link::<R> {
+        GenericLink::<R> {
             target: NavigationTarget::External("https://google.com".into()),
             "Click here to try to fix the failure."
         }

+ 4 - 4
packages/router/src/components/link.rs

@@ -9,7 +9,7 @@ use crate::utils::use_router_internal::use_router_internal;
 
 /// The properties for a [`Link`].
 #[derive(Props)]
-pub struct LinkProps<'a, R: Routable> {
+pub struct GenericLinkProps<'a, R: Routable> {
     /// A class to apply to the generate HTML anchor tag if the `target` route is active.
     pub active_class: Option<&'a str>,
     /// The children to render within the generated HTML anchor tag.
@@ -45,7 +45,7 @@ pub struct LinkProps<'a, R: Routable> {
     pub target: NavigationTarget<R>,
 }
 
-impl<R: Routable> Debug for LinkProps<'_, R> {
+impl<R: Routable> Debug for GenericLinkProps<'_, R> {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         f.debug_struct("LinkProps")
             .field("active_class", &self.active_class)
@@ -125,8 +125,8 @@ impl<R: Routable> Debug for LinkProps<'_, R> {
 /// # );
 /// ```
 #[allow(non_snake_case)]
-pub fn Link<'a, R: Routable + Clone>(cx: Scope<'a, LinkProps<'a, R>>) -> Element {
-    let LinkProps {
+pub fn GenericLink<'a, R: Routable + Clone>(cx: Scope<'a, GenericLinkProps<'a, R>>) -> Element {
+    let GenericLinkProps {
         active_class,
         children,
         class,

+ 1 - 1
packages/router/src/components/outlet.rs

@@ -44,6 +44,6 @@ use dioxus::prelude::*;
 /// # let _ = vdom.rebuild();
 /// # assert_eq!(dioxus_ssr::render(&vdom), "<h1>App</h1><p>Content</p>");
 /// ```
-pub fn Outlet<R: Routable + Clone>(cx: Scope) -> Element {
+pub fn GenericOutlet<R: Routable + Clone>(cx: Scope) -> Element {
     OutletContext::render::<R>(cx)
 }

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

@@ -3,7 +3,7 @@ use log::error;
 use std::{cell::RefCell, str::FromStr};
 
 use crate::{
-    prelude::{Outlet, RouterContext},
+    prelude::{GenericOutlet, GenericRouterContext},
     routable::Routable,
     router_cfg::RouterConfiguration,
 };
@@ -34,7 +34,7 @@ impl<R: Routable> From<RouterConfiguration<R>> for RouterCfg<R> {
 
 /// The props for [`Router`].
 #[derive(Props)]
-pub struct RouterProps<R: Routable>
+pub struct GenericRouterProps<R: Routable>
 where
     <R as FromStr>::Err: std::fmt::Display,
 {
@@ -44,7 +44,7 @@ where
     config: RouterCfg<R>,
 }
 
-impl<R: Routable> PartialEq for RouterProps<R>
+impl<R: Routable> PartialEq for GenericRouterProps<R>
 where
     <R as FromStr>::Err: std::fmt::Display,
 {
@@ -55,19 +55,19 @@ where
 }
 
 /// A component that renders the current route.
-pub fn Router<R: Routable + Clone>(cx: Scope<RouterProps<R>>) -> Element
+pub fn GenericRouter<R: Routable + Clone>(cx: Scope<GenericRouterProps<R>>) -> Element
 where
     <R as FromStr>::Err: std::fmt::Display,
 {
     use_context_provider(cx, || {
         #[allow(unreachable_code, unused_variables)]
-        if let Some(outer) = cx.consume_context::<RouterContext<R>>() {
+        if let Some(outer) = cx.consume_context::<GenericRouterContext<R>>() {
             let msg = "Router components should not be nested within each other";
             error!("{msg}, inner will be inactive and transparent");
             #[cfg(debug_assertions)]
             panic!("{}", msg);
         }
-        let router = RouterContext::new(
+        let router = GenericRouterContext::new(
             cx.props.config.config.take().unwrap_or_default(),
             cx.schedule_update_any(),
         );
@@ -82,6 +82,6 @@ where
     });
 
     render! {
-        Outlet::<R> {}
+        GenericOutlet::<R> {}
     }
 }

+ 4 - 4
packages/router/src/contexts/router.rs

@@ -19,7 +19,7 @@ pub enum NavigationFailure<R: Routable> {
 }
 
 /// A function the router will call after every routing update.
-pub type RoutingCallback<R> = Arc<dyn Fn(RouterContext<R>) -> Option<NavigationTarget<R>>>;
+pub type RoutingCallback<R> = Arc<dyn Fn(GenericRouterContext<R>) -> Option<NavigationTarget<R>>>;
 
 struct MutableRouterState<R>
 where
@@ -43,7 +43,7 @@ where
 }
 
 /// A collection of router data that manages all routing functionality.
-pub struct RouterContext<R>
+pub struct GenericRouterContext<R>
 where
     R: Routable,
 {
@@ -58,7 +58,7 @@ where
     failure_redirection_limit: fn(Scope) -> Element,
 }
 
-impl<R: Routable> Clone for RouterContext<R> {
+impl<R: Routable> Clone for GenericRouterContext<R> {
     fn clone(&self) -> Self {
         Self {
             state: self.state.clone(),
@@ -72,7 +72,7 @@ impl<R: Routable> Clone for RouterContext<R> {
     }
 }
 
-impl<R> RouterContext<R>
+impl<R> GenericRouterContext<R>
 where
     R: Routable,
 {

+ 3 - 2
packages/router/src/hooks/use_router.rs

@@ -1,11 +1,12 @@
 use dioxus::prelude::ScopeState;
 
 use crate::{
-    prelude::RouterContext, routable::Routable, utils::use_router_internal::use_router_internal,
+    prelude::GenericRouterContext, routable::Routable,
+    utils::use_router_internal::use_router_internal,
 };
 
 /// A hook that provides access to information about the router
-pub fn use_router<R: Routable + Clone>(cx: &ScopeState) -> &RouterContext<R> {
+pub fn use_generic_router<R: Routable + Clone>(cx: &ScopeState) -> &GenericRouterContext<R> {
     use_router_internal(cx)
         .as_ref()
         .expect("use_route must have access to a router")

+ 6 - 4
packages/router/src/utils/use_router_internal.rs

@@ -1,6 +1,6 @@
 use dioxus::prelude::{ScopeId, ScopeState};
 
-use crate::{contexts::router::RouterContext, routable::Routable};
+use crate::{contexts::router::GenericRouterContext, routable::Routable};
 
 /// A private hook to subscribe to the router.
 ///
@@ -12,9 +12,11 @@ use crate::{contexts::router::RouterContext, routable::Routable};
 /// - Otherwise [`Some`].
 ///
 /// [`use_router`]: crate::hooks::use_router
-pub(crate) fn use_router_internal<R: Routable>(cx: &ScopeState) -> &Option<RouterContext<R>> {
+pub(crate) fn use_router_internal<R: Routable>(
+    cx: &ScopeState,
+) -> &Option<GenericRouterContext<R>> {
     let inner = cx.use_hook(|| {
-        let router = cx.consume_context::<RouterContext<R>>()?;
+        let router = cx.consume_context::<GenericRouterContext<R>>()?;
 
         let id = cx.scope_id();
         router.subscribe(id);
@@ -25,7 +27,7 @@ pub(crate) fn use_router_internal<R: Routable>(cx: &ScopeState) -> &Option<Route
 }
 
 struct Subscription<R: Routable> {
-    router: RouterContext<R>,
+    router: GenericRouterContext<R>,
     id: ScopeId,
 }