Jelajahi Sumber

Fix router codegen

Jonathan Kelley 1 tahun lalu
induk
melakukan
fb4f97406c

+ 5 - 4
packages/core/src/nodes.rs

@@ -9,6 +9,7 @@ use crate::{
 };
 use crate::{Properties, VirtualDom};
 use core::panic;
+use std::ops::Deref;
 use std::rc::Rc;
 use std::vec;
 use std::{
@@ -16,7 +17,6 @@ use std::{
     cell::Cell,
     fmt::{Arguments, Debug},
 };
-use std::{ffi::c_void, ops::Deref};
 
 pub type TemplateId = &'static str;
 
@@ -513,7 +513,7 @@ pub struct VComponent {
     /// The function pointer of the component, known at compile time
     ///
     /// It is possible that components get folded at compile time, so these shouldn't be really used as a key
-    pub(crate) render_fn: *const c_void,
+    pub(crate) render_fn: TypeId,
 
     pub(crate) props: BoxedAnyProps,
 }
@@ -542,8 +542,9 @@ impl VComponent {
         // The properties must be valid until the next bump frame
         P: Properties + 'static,
     {
-        let component = Rc::new(component).as_component();
-        let render_fn = component.as_ref() as *const _ as *const c_void;
+        let component = Rc::new(component);
+        let render_fn = component.id();
+        let component = component.as_component();
         let vcomp = VProps::new(component, <P as Properties>::memoize, props, fn_name);
 
         VComponent {

+ 9 - 8
packages/core/src/properties.rs

@@ -1,4 +1,4 @@
-use std::rc::Rc;
+use std::{any::TypeId, rc::Rc};
 
 use crate::innerlude::*;
 
@@ -62,23 +62,25 @@ where
 }
 
 /// Any component that implements the `ComponentFn` trait can be used as a component.
-pub trait ComponentFunction<Props, Marker> {
-    type Props;
+pub trait ComponentFunction<Props, Marker = ()>: 'static {
+    /// Get the type id of the component.
+    fn id(&self) -> TypeId {
+        TypeId::of::<Self>()
+    }
+
     /// Convert the component to a function that takes props and returns an element.
     fn as_component(self: Rc<Self>) -> Component<Props>;
 }
 
 /// Accept pre-formed component render functions as components
-impl<P> ComponentFunction<P, ()> for Component<P> {
-    type Props = P;
+impl<P: 'static> ComponentFunction<P> for Component<P> {
     fn as_component(self: Rc<Self>) -> Component<P> {
         self.as_ref().clone()
     }
 }
 
 /// Accept any callbacks that take props
-impl<F: Fn(P) -> Element + 'static, P> ComponentFunction<P, ()> for F {
-    type Props = P;
+impl<F: Fn(P) -> Element + 'static, P> ComponentFunction<P> for F {
     fn as_component(self: Rc<Self>) -> Component<P> {
         self
     }
@@ -87,7 +89,6 @@ impl<F: Fn(P) -> Element + 'static, P> ComponentFunction<P, ()> for F {
 /// Accept any callbacks that take no props
 pub struct EmptyMarker;
 impl<F: Fn() -> Element + 'static> ComponentFunction<(), EmptyMarker> for F {
-    type Props = ();
     fn as_component(self: Rc<Self>) -> Rc<dyn Fn(()) -> Element> {
         Rc::new(move |_| self())
     }

+ 10 - 9
packages/router-macro/src/lib.rs

@@ -605,18 +605,19 @@ impl RouteEnum {
 
     fn component_impl(&self) -> TokenStream2 {
         let name = &self.name;
+        let props = quote! { ::std::rc::Rc<::std::cell::Cell<::dioxus_router::prelude::RouterConfig<#name>>> };
 
         quote! {
-            impl dioxus_core::ComponentFunction<#name> for #name {
-                type Props = ::std::rc::Rc<::std::cell::Cell<::dioxus_router::prelude::RouterConfig<#name>>>;
-
-                fn call(&self, props: Self::Props) -> dioxus_core::Element {
-                    let initial_route = self.clone();
-                    rsx! {
-                        ::dioxus_router::prelude::Router::<#name> {
-                            config: move || props.take().initial_route(initial_route)
+            impl dioxus_core::ComponentFunction<#props> for #name {
+                fn as_component(self: ::std::rc::Rc<Self>) -> Component<#props> {
+                    ::std::rc::Rc::new(move |props| {
+                        let initial_route = self.as_ref().clone();
+                        rsx! {
+                            ::dioxus_router::prelude::Router::<#name> {
+                                config: move || props.take().initial_route(initial_route)
+                            }
                         }
-                    }
+                    })
                 }
             }
         }