feat: Rc-backed ChildrenFn (#1669)

This commit is contained in:
Baptiste 2023-09-08 13:44:50 +02:00 committed by GitHub
parent de44b1f91f
commit b3a4c95dad
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 72 additions and 20 deletions

62
leptos/src/children.rs Normal file
View file

@ -0,0 +1,62 @@
use leptos_dom::Fragment;
use std::rc::Rc;
/// The most common type for the `children` property on components,
/// which can only be called once.
pub type Children = Box<dyn FnOnce() -> Fragment>;
/// A type for the `children` property on components that can be called
/// more than once.
pub type ChildrenFn = Rc<dyn Fn() -> Fragment>;
/// A type for the `children` property on components that can be called
/// more than once, but may mutate the children.
pub type ChildrenFnMut = Box<dyn FnMut() -> Fragment>;
// This is to still support components that accept `Box<dyn Fn() -> Fragment>` as a children.
type BoxedChildrenFn = Box<dyn Fn() -> Fragment>;
#[doc(hidden)]
pub trait ToChildren<F> {
fn to_children(f: F) -> Self;
}
impl<F> ToChildren<F> for Children
where
F: FnOnce() -> Fragment + 'static,
{
#[inline]
fn to_children(f: F) -> Self {
Box::new(f)
}
}
impl<F> ToChildren<F> for ChildrenFn
where
F: Fn() -> Fragment + 'static,
{
#[inline]
fn to_children(f: F) -> Self {
Rc::new(f)
}
}
impl<F> ToChildren<F> for ChildrenFnMut
where
F: FnMut() -> Fragment + 'static,
{
#[inline]
fn to_children(f: F) -> Self {
Box::new(f)
}
}
impl<F> ToChildren<F> for BoxedChildrenFn
where
F: Fn() -> Fragment + 'static,
{
#[inline]
fn to_children(f: F) -> Self {
Box::new(f)
}
}

View file

@ -204,20 +204,10 @@ pub use typed_builder;
pub use typed_builder::Optional;
#[doc(hidden)]
pub use typed_builder_macro;
mod children;
pub use children::*;
extern crate self as leptos;
/// The most common type for the `children` property on components,
/// which can only be called once.
pub type Children = Box<dyn FnOnce() -> Fragment>;
/// A type for the `children` property on components that can be called
/// more than once.
pub type ChildrenFn = Box<dyn Fn() -> Fragment>;
/// A type for the `children` property on components that can be called
/// more than once, but may mutate the children.
pub type ChildrenFnMut = Box<dyn FnMut() -> Fragment>;
/// A type for taking anything that implements [`IntoAttribute`].
///
/// ```rust

View file

@ -1,5 +1,5 @@
use leptos::component;
use leptos_dom::{Fragment, IntoView};
use leptos::{component, ChildrenFn};
use leptos_dom::IntoView;
use leptos_reactive::{create_memo, signal_prelude::*};
/// A component that will show its children when the `when` condition is `true`,
@ -38,7 +38,7 @@ pub fn Show<F, W, IV>(
/// The scope the component is running in
/// The components Show wraps
children: Box<dyn Fn() -> Fragment>,
children: ChildrenFn,
/// A closure that returns a bool that determines whether this thing runs
when: W,
/// A closure that returns what gets rendered if the when statement is false

View file

@ -61,14 +61,14 @@ pub fn Suspense<F, E, V>(
/// Returns a fallback UI that will be shown while `async` [`Resource`](leptos_reactive::Resource)s are still loading.
fallback: F,
/// Children will be displayed once all `async` [`Resource`](leptos_reactive::Resource)s have resolved.
children: Box<dyn Fn() -> V>,
children: Rc<dyn Fn() -> V>,
) -> impl IntoView
where
F: Fn() -> E + 'static,
E: IntoView,
V: IntoView + 'static,
{
let orig_children = Rc::new(children);
let orig_children = children;
let context = SuspenseContext::new();
#[cfg(not(any(feature = "csr", feature = "hydrate")))]

View file

@ -114,7 +114,7 @@ where
}
}
})
.children(Box::new(move || {
.children(Rc::new(move || {
let frag = children().into_view();
if let Some(suspense_context) = use_context::<SuspenseContext>()

View file

@ -124,7 +124,7 @@ pub(crate) fn component_to_tokens(
.children({
#(#clonables)*
Box::new(move || #children #view_marker)
::leptos::ToChildren::to_children(move || #children #view_marker)
})
}
}

View file

@ -130,7 +130,7 @@ pub(crate) fn slot_to_tokens(
.children({
#(#clonables)*
Box::new(move || #children #view_marker)
::leptos::ToChildren::to_children(move || #children #view_marker)
})
}
}