try not double boxing

This commit is contained in:
Evan Almloff committed 2024-01-17 15:07:45 -06:00
1 parent 0c532c5e0c
commit dab87c0144
11 files changed
+166 -103

No files matched your search

+13 -8
View File
@@ -1,7 +1,7 @@
use crate::{nodes::RenderReturn, Component}; use crate::{nodes::RenderReturn, ComponentFunction};
use std::{any::Any, panic::AssertUnwindSafe}; use std::{any::Any, panic::AssertUnwindSafe};
pub type BoxedAnyProps = Box<dyn AnyProps>; pub(crate) type BoxedAnyProps = Box<dyn AnyProps>;
/// A trait that essentially allows VComponentProps to be used generically /// A trait that essentially allows VComponentProps to be used generically
pub(crate) trait AnyProps { pub(crate) trait AnyProps {
@@ -12,8 +12,8 @@ pub(crate) trait AnyProps {
} }
/// Create a new boxed props object. /// Create a new boxed props object.
pub fn new_any_props<P: 'static + Clone>( pub(crate) fn new_any_props<F: ComponentFunction<P, M>, P: Clone + 'static, M: 'static>(
render_fn: Component<P>, render_fn: F,
memo: fn(&P, &P) -> bool, memo: fn(&P, &P) -> bool,
props: P, props: P,
name: &'static str, name: &'static str,
@@ -23,17 +23,21 @@ pub fn new_any_props<P: 'static + Clone>(
memo, memo,
props, props,
name, name,
phantom: std::marker::PhantomData,
}) })
} }
struct VProps<P> { struct VProps<F: ComponentFunction<P, M>, P, M> {
render_fn: Component<P>, render_fn: F,
memo: fn(&P, &P) -> bool, memo: fn(&P, &P) -> bool,
props: P, props: P,
name: &'static str, name: &'static str,
phantom: std::marker::PhantomData<M>,
} }
impl<P: Clone + 'static> AnyProps for VProps<P> { impl<F: ComponentFunction<P, M> + Clone, P: Clone + 'static, M: 'static> AnyProps
for VProps<F, P, M>
{
fn memoize(&self, other: &dyn Any) -> bool { fn memoize(&self, other: &dyn Any) -> bool {
match other.downcast_ref::<P>() { match other.downcast_ref::<P>() {
Some(other) => (self.memo)(&self.props, other), Some(other) => (self.memo)(&self.props, other),
@@ -47,7 +51,7 @@ impl<P: Clone + 'static> AnyProps for VProps<P> {
fn render(&self) -> RenderReturn { fn render(&self) -> RenderReturn {
let res = std::panic::catch_unwind(AssertUnwindSafe(move || { let res = std::panic::catch_unwind(AssertUnwindSafe(move || {
(self.render_fn)(self.props.clone()) self.render_fn.rebuild(self.props.clone())
})); }));
match res { match res {
@@ -67,6 +71,7 @@ impl<P: Clone + 'static> AnyProps for VProps<P> {
memo: self.memo, memo: self.memo,
props: self.props.clone(), props: self.props.clone(),
name: self.name, name: self.name,
phantom: std::marker::PhantomData,
}) })
} }
} }
+1 -3
View File
@@ -520,7 +520,7 @@ pub struct VComponent {
impl VComponent { impl VComponent {
/// Create a new [`VComponent`] variant /// Create a new [`VComponent`] variant
pub fn new<P, M>( pub fn new<P, M: 'static>(
component: impl ComponentFunction<P, M>, component: impl ComponentFunction<P, M>,
props: P, props: P,
fn_name: &'static str, fn_name: &'static str,
@@ -528,9 +528,7 @@ impl VComponent {
where where
P: Properties + 'static, P: Properties + 'static,
{ {
let component = Rc::new(component);
let render_fn = component.id(); let render_fn = component.id();
let component = component.as_component();
let props = new_any_props(component, <P as Properties>::memoize, props, fn_name); let props = new_any_props(component, <P as Properties>::memoize, props, fn_name);
VComponent { VComponent {
+24 -15
View File
@@ -1,6 +1,9 @@
use std::any::Any; use std::any::Any;
use crate::{properties::ComponentFunction, Component, VirtualDom}; use crate::{
properties::{ComponentFunction, RootProps},
VComponent, VirtualDom,
};
/// A boxed object that can be injected into a component's context. /// A boxed object that can be injected into a component's context.
pub struct BoxedContext(Box<dyn ClonableAny>); pub struct BoxedContext(Box<dyn ClonableAny>);
@@ -40,32 +43,38 @@ impl<T: Any + Clone> ClonableAny for T {
} }
/// The platform-independent part of the config needed to launch an application. /// The platform-independent part of the config needed to launch an application.
pub struct CrossPlatformConfig<Props: Clone + 'static> { pub struct CrossPlatformConfig {
/// The root component function. /// The root component function.
pub component: Component<Props>, component: VComponent,
/// The props for the root component.
pub props: Props,
/// The contexts to provide to the root component. /// The contexts to provide to the root component.
pub root_contexts: Vec<BoxedContext>, root_contexts: Vec<BoxedContext>,
} }
impl<Props: Clone + 'static> CrossPlatformConfig<Props> { impl CrossPlatformConfig {
/// Create a new cross-platform config. /// Create a new cross-platform config.
pub fn new<M>( pub fn new<Props: Clone + 'static, M: 'static>(
component: impl ComponentFunction<Props, M>, component: impl ComponentFunction<Props, M>,
props: Props, props: Props,
root_contexts: Vec<BoxedContext>, root_contexts: Vec<BoxedContext>,
) -> Self { ) -> Self {
Self { Self {
component: ComponentFunction::as_component(std::rc::Rc::new(component)), component: VComponent::new(
props, move |props: RootProps<Props>| component.rebuild(props.0),
RootProps(props),
"root",
),
root_contexts, root_contexts,
} }
} }
/// Push a new context into the root component's context.
pub fn push_context<T: Any + Clone + 'static>(&mut self, context: T) {
self.root_contexts.push(BoxedContext::new(context));
}
/// Build a virtual dom from the config. /// Build a virtual dom from the config.
pub fn build_vdom(self) -> VirtualDom { pub fn build_vdom(self) -> VirtualDom {
let mut vdom = VirtualDom::new_with_props(self.component, self.props); let mut vdom = VirtualDom::new_with_component(self.component);
for context in self.root_contexts { for context in self.root_contexts {
vdom.insert_boxed_root_context(context); vdom.insert_boxed_root_context(context);
@@ -76,18 +85,18 @@ impl<Props: Clone + 'static> CrossPlatformConfig<Props> {
} }
/// A builder to launch a specific platform. /// A builder to launch a specific platform.
pub trait PlatformBuilder<Props: Clone + 'static> { pub trait PlatformBuilder {
/// The platform-specific config needed to launch an application. /// The platform-specific config needed to launch an application.
type Config: Default; type Config: Default;
/// Launch the app. /// Launch the app.
fn launch(config: CrossPlatformConfig<Props>, platform_config: Self::Config); fn launch(config: CrossPlatformConfig, platform_config: Self::Config);
} }
impl<Props: Clone + 'static> PlatformBuilder<Props> for () { impl PlatformBuilder for () {
type Config = (); type Config = ();
fn launch(_: CrossPlatformConfig<Props>, _: Self::Config) { fn launch(_: CrossPlatformConfig, _: Self::Config) {
panic!("No platform is currently enabled. Please enable a platform feature for the dioxus crate."); panic!("No platform is currently enabled. Please enable a platform feature for the dioxus crate.");
} }
} }
+36 -11
View File
@@ -1,4 +1,4 @@
use std::{any::TypeId, rc::Rc}; use std::any::TypeId;
use crate::innerlude::*; use crate::innerlude::*;
@@ -45,6 +45,31 @@ impl Properties for () {
} }
} }
/// Root properties never need to be memoized, so we can use a dummy implementation.
pub(crate) struct RootProps<P>(pub P);
impl<P> Clone for RootProps<P>
where
P: Clone,
{
fn clone(&self) -> Self {
Self(self.0.clone())
}
}
impl<P> Properties for RootProps<P>
where
P: Clone + 'static,
{
type Builder = P;
fn builder() -> Self::Builder {
todo!()
}
fn memoize(&self, _other: &Self) -> bool {
true
}
}
// We allow components to use the () generic parameter if they have no props. This impl enables the "build" method // We allow components to use the () generic parameter if they have no props. This impl enables the "build" method
// that the macros use to anonymously complete prop construction. // that the macros use to anonymously complete prop construction.
pub struct EmptyBuilder; pub struct EmptyBuilder;
@@ -62,35 +87,35 @@ where
} }
/// Any component that implements the `ComponentFn` trait can be used as a component. /// Any component that implements the `ComponentFn` trait can be used as a component.
pub trait ComponentFunction<Props, Marker = ()>: 'static { pub trait ComponentFunction<Props, Marker = ()>: Clone + 'static {
/// Get the type id of the component. /// Get the type id of the component.
fn id(&self) -> TypeId { fn id(&self) -> TypeId {
TypeId::of::<Self>() TypeId::of::<Self>()
} }
/// Convert the component to a function that takes props and returns an element. /// Convert the component to a function that takes props and returns an element.
fn as_component(self: Rc<Self>) -> Component<Props>; fn rebuild(&self, props: Props) -> Element;
} }
/// Accept pre-formed component render functions as components /// Accept pre-formed component render functions as components
impl<P: 'static> ComponentFunction<P> for Component<P> { impl<P: 'static> ComponentFunction<P> for Component<P> {
fn as_component(self: Rc<Self>) -> Component<P> { fn rebuild(&self, props: P) -> Element {
self.as_ref().clone() (self)(props)
} }
} }
/// Accept any callbacks that take props /// Accept any callbacks that take props
impl<F: Fn(P) -> Element + 'static, P> ComponentFunction<P> for F { impl<F: Fn(P) -> Element + Clone + 'static, P> ComponentFunction<P> for F {
fn as_component(self: Rc<Self>) -> Component<P> { fn rebuild(&self, props: P) -> Element {
self self(props)
} }
} }
/// Accept any callbacks that take no props /// Accept any callbacks that take no props
pub struct EmptyMarker; pub struct EmptyMarker;
impl<F: Fn() -> Element + 'static> ComponentFunction<(), EmptyMarker> for F { impl<F: Fn() -> Element + Clone + 'static> ComponentFunction<(), EmptyMarker> for F {
fn as_component(self: Rc<Self>) -> Rc<dyn Fn(()) -> Element> { fn rebuild(&self, _: ()) -> Element {
Rc::new(move |_| self()) self()
} }
} }
+50 -14
View File
@@ -3,7 +3,6 @@
//! This module provides the primary mechanics to create a hook-based, concurrent VDOM for Rust. //! This module provides the primary mechanics to create a hook-based, concurrent VDOM for Rust.
use crate::{ use crate::{
any_props::new_any_props,
arena::ElementId, arena::ElementId,
innerlude::{ innerlude::{
DirtyScope, ElementRef, ErrorBoundary, NoOpMutations, SchedulerMsg, ScopeState, VNodeMount, DirtyScope, ElementRef, ErrorBoundary, NoOpMutations, SchedulerMsg, ScopeState, VNodeMount,
@@ -11,10 +10,10 @@ use crate::{
}, },
nodes::RenderReturn, nodes::RenderReturn,
nodes::{Template, TemplateId}, nodes::{Template, TemplateId},
properties::ComponentFunction, properties::RootProps,
runtime::{Runtime, RuntimeGuard}, runtime::{Runtime, RuntimeGuard},
scopes::ScopeId, scopes::ScopeId,
AttributeValue, BoxedContext, Element, Event, Mutations, Task, AttributeValue, BoxedContext, ComponentFunction, Element, Event, Mutations, Task, VComponent,
}; };
use futures_util::{pin_mut, StreamExt}; use futures_util::{pin_mut, StreamExt};
use rustc_hash::{FxHashMap, FxHashSet}; use rustc_hash::{FxHashMap, FxHashSet};
@@ -230,13 +229,6 @@ impl VirtualDom {
Self::new_with_props(app, ()) Self::new_with_props(app, ())
} }
/// Create a new virtualdom and build it immediately
pub fn prebuilt(app: fn() -> Element) -> Self {
let mut dom = Self::new(app);
dom.rebuild_in_place();
dom
}
/// Create a new VirtualDom with the given properties for the root component. /// Create a new VirtualDom with the given properties for the root component.
/// ///
/// # Description /// # Description
@@ -271,6 +263,53 @@ impl VirtualDom {
root: impl ComponentFunction<P, M>, root: impl ComponentFunction<P, M>,
root_props: P, root_props: P,
) -> Self { ) -> Self {
let vcomponent = VComponent::new(
move |props: RootProps<P>| root.rebuild(props.0),
RootProps(root_props),
"root",
);
Self::new_with_component(vcomponent)
}
/// Create a new virtualdom and build it immediately
pub fn prebuilt(app: fn() -> Element) -> Self {
let mut dom = Self::new(app);
dom.rebuild_in_place();
dom
}
/// Create a new VirtualDom with the given properties for the root component.
///
/// # Description
///
/// Later, the props can be updated by calling "update" with a new set of props, causing a set of re-renders.
///
/// This is useful when a component tree can be driven by external state (IE SSR) but it would be too expensive
/// to toss out the entire tree.
///
///
/// # Example
/// ```rust, ignore
/// #[derive(PartialEq, Props)]
/// struct SomeProps {
/// name: &'static str
/// }
///
/// fn Example(cx: SomeProps) -> Element {
/// rsx!{ div{ "hello {cx.name}" } })
/// }
///
/// let dom = VirtualDom::new(Example);
/// ```
///
/// Note: the VirtualDom is not progressed on creation. You must either "run_with_deadline" or use "rebuild" to progress it.
///
/// ```rust, ignore
/// let mut dom = VirtualDom::new_from_root(VComponent::new(Example, SomeProps { name: "jane" }, "Example"));
/// let mutations = dom.rebuild();
/// ```
pub fn new_with_component(root: VComponent) -> Self {
let (tx, rx) = futures_channel::mpsc::unbounded(); let (tx, rx) = futures_channel::mpsc::unbounded();
let mut dom = Self { let mut dom = Self {
@@ -285,10 +324,7 @@ impl VirtualDom {
suspended_scopes: Default::default(), suspended_scopes: Default::default(),
}; };
let root = dom.new_scope( let root = dom.new_scope(root.props, "app");
new_any_props(Rc::new(root).as_component(), |_, _| true, root_props, "app"),
"app",
);
// Unlike react, we provide a default error boundary that just renders the error as a string // Unlike react, we provide a default error boundary that just renders the error as a string
root.context() root.context()
+4 -5
View File
@@ -18,7 +18,6 @@ use dioxus_html::{
use std::{ use std::{
cell::{Cell, RefCell}, cell::{Cell, RefCell},
collections::HashMap, collections::HashMap,
marker::PhantomData,
rc::Rc, rc::Rc,
sync::Arc, sync::Arc,
}; };
@@ -29,10 +28,10 @@ use tao::{
}; };
/// The single top-level object that manages all the running windows, assets, shortcuts, etc /// The single top-level object that manages all the running windows, assets, shortcuts, etc
pub(crate) struct App<Props: Clone + 'static> { pub(crate) struct App {
// move the props into a cell so we can pop it out later to create the first window // move the props into a cell so we can pop it out later to create the first window
// iOS panics if we create a window before the event loop is started, so we toss them into a cell // iOS panics if we create a window before the event loop is started, so we toss them into a cell
pub(crate) dioxus_config: Cell<Option<CrossPlatformConfig<Props>>>, pub(crate) dioxus_config: Cell<Option<CrossPlatformConfig>>,
pub(crate) cfg: Cell<Option<Config>>, pub(crate) cfg: Cell<Option<Config>>,
// Stuff we need mutable access to // Stuff we need mutable access to
@@ -59,10 +58,10 @@ pub struct SharedContext {
pub(crate) target: EventLoopWindowTarget<UserWindowEvent>, pub(crate) target: EventLoopWindowTarget<UserWindowEvent>,
} }
impl<Props: Clone + 'static> App<Props> { impl App {
pub fn new( pub fn new(
cfg: Config, cfg: Config,
dioxus_config: CrossPlatformConfig<Props>, dioxus_config: CrossPlatformConfig,
) -> (EventLoop<UserWindowEvent>, Self) { ) -> (EventLoop<UserWindowEvent>, Self) {
let event_loop = EventLoopBuilder::<UserWindowEvent>::with_user_event().build(); let event_loop = EventLoopBuilder::<UserWindowEvent>::with_user_event().build();
+3 -6
View File
@@ -10,10 +10,7 @@ use tao::event::{Event, StartCause, WindowEvent};
/// ///
/// This will block the main thread, and *must* be spawned on the main thread. This function does not assume any runtime /// This will block the main thread, and *must* be spawned on the main thread. This function does not assume any runtime
/// and is equivalent to calling launch_with_props with the tokio feature disabled. /// and is equivalent to calling launch_with_props with the tokio feature disabled.
pub fn launch_with_props_blocking<Props: Clone + 'static>( pub fn launch_with_props_blocking(dioxus_cfg: CrossPlatformConfig, desktop_config: Config) {
dioxus_cfg: CrossPlatformConfig<Props>,
desktop_config: Config,
) {
let (event_loop, mut app) = App::new(desktop_config, dioxus_cfg); let (event_loop, mut app) = App::new(desktop_config, dioxus_cfg);
event_loop.run(move |window_event, _, control_flow| { event_loop.run(move |window_event, _, control_flow| {
@@ -53,10 +50,10 @@ pub fn launch_with_props_blocking<Props: Clone + 'static>(
/// The desktop renderer platform /// The desktop renderer platform
pub struct DesktopPlatform; pub struct DesktopPlatform;
impl<Props: Clone + 'static> PlatformBuilder<Props> for DesktopPlatform { impl PlatformBuilder for DesktopPlatform {
type Config = Config; type Config = Config;
fn launch(config: dioxus_core::CrossPlatformConfig<Props>, platform_config: Self::Config) { fn launch(config: dioxus_core::CrossPlatformConfig, platform_config: Self::Config) {
#[cfg(feature = "tokio")] #[cfg(feature = "tokio")]
tokio::runtime::Builder::new_multi_thread() tokio::runtime::Builder::new_multi_thread()
.enable_all() .enable_all()
+26 -27
View File
@@ -7,19 +7,17 @@ use dioxus_core::prelude::*;
use dioxus_core::{BoxedContext, CrossPlatformConfig, PlatformBuilder}; use dioxus_core::{BoxedContext, CrossPlatformConfig, PlatformBuilder};
/// A builder for a fullstack app. /// A builder for a fullstack app.
pub struct LaunchBuilder<Props: Clone + 'static, Platform: PlatformBuilder<Props> = CurrentPlatform> pub struct LaunchBuilder<Platform: PlatformBuilder = CurrentPlatform> {
{ cross_platform_config: CrossPlatformConfig,
cross_platform_config: CrossPlatformConfig<Props>, platform_config: Option<<Platform as PlatformBuilder>::Config>,
platform_config: Option<<Platform as PlatformBuilder<Props>>::Config>,
} }
// Default platform builder // Default platform builder
impl<Props: Clone + 'static> LaunchBuilder<Props> { impl LaunchBuilder {
/// Create a new builder for your application. This will create a launch configuration for the current platform based on the features enabled on the `dioxus` crate. /// Create a new builder for your application. This will create a launch configuration for the current platform based on the features enabled on the `dioxus` crate.
pub fn new<M>(component: impl ComponentFunction<Props, M>) -> Self pub fn new<Props: Clone + Default + 'static, M: 'static>(
where component: impl ComponentFunction<Props, M>,
Props: Default, ) -> Self {
{
Self { Self {
cross_platform_config: CrossPlatformConfig::new( cross_platform_config: CrossPlatformConfig::new(
component, component,
@@ -29,28 +27,29 @@ impl<Props: Clone + 'static> LaunchBuilder<Props> {
platform_config: None, platform_config: None,
} }
} }
/// Create a new builder for your application with some root props. This will create a launch configuration for the current platform based on the features enabled on the `dioxus` crate.
pub fn new_with_props<Props: Clone + 'static, M: 'static>(
component: impl ComponentFunction<Props, M>,
props: Props,
) -> Self {
Self {
cross_platform_config: CrossPlatformConfig::new(component, props, Default::default()),
platform_config: None,
}
}
} }
impl<Props: Clone + 'static, Platform: PlatformBuilder<Props>> LaunchBuilder<Props, Platform> { impl<Platform: PlatformBuilder> LaunchBuilder<Platform> {
/// Pass some props to your application.
pub fn props(mut self, props: Props) -> Self {
self.cross_platform_config.props = props;
self
}
/// Inject state into the root component's context. /// Inject state into the root component's context.
pub fn context(mut self, state: impl Any + Clone + 'static) -> Self { pub fn context(mut self, state: impl Any + Clone + 'static) -> Self {
self.cross_platform_config self.cross_platform_config
.root_contexts .push_context(BoxedContext::new(state));
.push(BoxedContext::new(state));
self self
} }
/// Provide a platform-specific config to the builder. /// Provide a platform-specific config to the builder.
pub fn cfg( pub fn cfg(mut self, config: impl Into<Option<<Platform as PlatformBuilder>::Config>>) -> Self {
mut self,
config: impl Into<Option<<Platform as PlatformBuilder<Props>>::Config>>,
) -> Self {
if let Some(config) = config.into() { if let Some(config) = config.into() {
self.platform_config = Some(config); self.platform_config = Some(config);
} }
@@ -68,7 +67,7 @@ impl<Props: Clone + 'static, Platform: PlatformBuilder<Props>> LaunchBuilder<Pro
} }
#[cfg(feature = "web")] #[cfg(feature = "web")]
impl<Props: Clone + 'static> LaunchBuilder<Props, dioxus_web::WebPlatform> { impl LaunchBuilder<dioxus_web::WebPlatform> {
/// Launch your web application. /// Launch your web application.
pub fn launch_web(self) { pub fn launch_web(self) {
dioxus_web::WebPlatform::launch( dioxus_web::WebPlatform::launch(
@@ -79,7 +78,7 @@ impl<Props: Clone + 'static> LaunchBuilder<Props, dioxus_web::WebPlatform> {
} }
#[cfg(feature = "desktop")] #[cfg(feature = "desktop")]
impl<Props: Clone + 'static> LaunchBuilder<Props, dioxus_desktop::DesktopPlatform> { impl LaunchBuilder<dioxus_desktop::DesktopPlatform> {
/// Launch your desktop application. /// Launch your desktop application.
pub fn launch_desktop(self) { pub fn launch_desktop(self) {
dioxus_desktop::DesktopPlatform::launch( dioxus_desktop::DesktopPlatform::launch(
@@ -97,7 +96,7 @@ type CurrentPlatform = dioxus_web::WebPlatform;
type CurrentPlatform = (); type CurrentPlatform = ();
/// Launch your application without any additional configuration. See [`LaunchBuilder`] for more options. /// Launch your application without any additional configuration. See [`LaunchBuilder`] for more options.
pub fn launch<Props, Marker>(component: impl ComponentFunction<Props, Marker>) pub fn launch<Props, Marker: 'static>(component: impl ComponentFunction<Props, Marker>)
where where
Props: Default + Clone + 'static, Props: Default + Clone + 'static,
{ {
@@ -106,7 +105,7 @@ where
#[cfg(feature = "web")] #[cfg(feature = "web")]
/// Launch your web application without any additional configuration. See [`LaunchBuilder`] for more options. /// Launch your web application without any additional configuration. See [`LaunchBuilder`] for more options.
pub fn launch_web<Props, Marker>(component: impl ComponentFunction<Props, Marker>) pub fn launch_web<Props, Marker: 'static>(component: impl ComponentFunction<Props, Marker>)
where where
Props: Default + Clone + 'static, Props: Default + Clone + 'static,
{ {
@@ -115,7 +114,7 @@ where
#[cfg(feature = "desktop")] #[cfg(feature = "desktop")]
/// Launch your desktop application without any additional configuration. See [`LaunchBuilder`] for more options. /// Launch your desktop application without any additional configuration. See [`LaunchBuilder`] for more options.
pub fn launch_desktop<Props, Marker>(component: impl ComponentFunction<Props, Marker>) pub fn launch_desktop<Props, Marker: 'static>(component: impl ComponentFunction<Props, Marker>)
where where
Props: Default + Clone + 'static, Props: Default + Clone + 'static,
{ {
+6 -8
View File
@@ -609,15 +609,13 @@ impl RouteEnum {
quote! { quote! {
impl dioxus_core::ComponentFunction<#props> for #name { impl dioxus_core::ComponentFunction<#props> for #name {
fn as_component(self: ::std::rc::Rc<Self>) -> Component<#props> { fn rebuild(&self, props: #props) -> dioxus_core::Element {
::std::rc::Rc::new(move |props| { let initial_route = self.clone();
let initial_route = self.as_ref().clone(); rsx! {
rsx! { ::dioxus_router::prelude::Router::<#name> {
::dioxus_router::prelude::Router::<#name> { config: move || props.take().initial_route(initial_route)
config: move || props.take().initial_route(initial_route)
}
} }
}) }
} }
} }
} }
+1 -4
View File
@@ -99,10 +99,7 @@ mod rehydrate;
/// wasm_bindgen_futures::spawn_local(app_fut); /// wasm_bindgen_futures::spawn_local(app_fut);
/// } /// }
/// ``` /// ```
pub async fn run_with_props<Props: Clone + 'static>( pub async fn run_with_props(dioxus_config: CrossPlatformConfig, web_config: Config) {
dioxus_config: CrossPlatformConfig<Props>,
web_config: Config,
) {
tracing::info!("Starting up"); tracing::info!("Starting up");
let mut dom = dioxus_config.build_vdom(); let mut dom = dioxus_config.build_vdom();
+2 -2
View File
@@ -5,10 +5,10 @@ use crate::Config;
/// The web renderer platform /// The web renderer platform
pub struct WebPlatform; pub struct WebPlatform;
impl<Props: Clone + 'static> PlatformBuilder<Props> for WebPlatform { impl PlatformBuilder for WebPlatform {
type Config = Config; type Config = Config;
fn launch(config: CrossPlatformConfig<Props>, platform_config: Self::Config) { fn launch(config: CrossPlatformConfig, platform_config: Self::Config) {
wasm_bindgen_futures::spawn_local(async move { wasm_bindgen_futures::spawn_local(async move {
crate::run_with_props(config, platform_config).await; crate::run_with_props(config, platform_config).await;
}); });