wip: move children onto scope

This commit is contained in:
Jonathan Kelley 2021-11-01 03:49:32 -04:00
parent d1b294fff0
commit f438bbcfd2
6 changed files with 85 additions and 19 deletions

View file

@ -37,7 +37,7 @@ once_cell = "1.8.0"
indexmap = "1.7.0"
# # Serialize the Edits for use in Webview/Liveview instances
# Serialize the Edits for use in Webview/Liveview instances
serde = { version = "1", features = ["derive"], optional = true }
serde_repr = { version = "0.1.7", optional = true }

View file

@ -66,15 +66,15 @@ pub(crate) mod innerlude {
pub use crate::innerlude::{
Context, DioxusElement, DomEdit, Element, ElementId, EventPriority, MountType, Mutations,
NodeFactory, Properties, SchedulerMsg, ScopeId, SuspendedContext, TaskHandle, TestDom,
ThreadsafeVirtualDom, UserEvent, VNode, VirtualDom, FC,
NodeFactory, Properties, SchedulerMsg, ScopeChildren, ScopeId, SuspendedContext, TaskHandle,
TestDom, ThreadsafeVirtualDom, UserEvent, VNode, VirtualDom, FC,
};
pub mod prelude {
pub use crate::component::{fc_to_builder, Fragment, Properties, Scope};
pub use crate::context::Context;
pub use crate::hooks::*;
pub use crate::innerlude::{DioxusElement, Element, LazyNodes, NodeFactory, FC};
pub use crate::innerlude::{DioxusElement, Element, LazyNodes, NodeFactory, ScopeChildren, FC};
pub use crate::nodes::VNode;
pub use crate::VirtualDom;
}

View file

@ -726,3 +726,65 @@ impl IntoVNode<'_> for Arguments<'_> {
cx.text(self)
}
}
/// Access the children elements passed into the component
///
/// This enables patterns where a component is passed children from its parent.
///
/// ## Details
///
/// Unlike React, Dioxus allows *only* lists of children to be passed from parent to child - not arbitrary functions
/// or classes. If you want to generate nodes instead of accepting them as a list, consider declaring a closure
/// on the props that takes Context.
///
/// If a parent passes children into a component, the child will always re-render when the parent re-renders. In other
/// words, a component cannot be automatically memoized if it borrows nodes from its parent, even if the component's
/// props are valid for the static lifetime.
///
/// ## Example
///
/// ```rust
/// const App: FC<()> = |(cx, props)|{
/// cx.render(rsx!{
/// CustomCard {
/// h1 {}
/// p {}
/// }
/// })
/// }
///
/// const CustomCard: FC<()> = |(cx, props)|{
/// cx.render(rsx!{
/// div {
/// h1 {"Title card"}
/// {props.children}
/// }
/// })
/// }
/// ```
///
/// ## Notes:
///
/// This method returns a "ScopeChildren" object. This object is copy-able and preserve the correct lifetime.
pub struct ScopeChildren<'a> {
root: Option<VNode<'a>>,
}
impl IntoIterator for &ScopeChildren<'_> {
type Item = Self;
type IntoIter = std::iter::Once<Self>;
fn into_iter(self) -> Self::IntoIter {
todo!()
}
}
impl<'a> IntoVNode<'a> for &ScopeChildren<'a> {
fn into_vnode(self, cx: NodeFactory<'a>) -> VNode<'a> {
match &self.root {
Some(n) => n.decouple(),
None => cx.fragment_from_iter(None as Option<VNode>),
}
}
}

View file

@ -340,8 +340,6 @@ impl ScopeInner {
let render: &dyn for<'b> Fn(&'b ScopeInner) -> Element<'b> = unsafe { &*self.caller };
// Todo: see if we can add stronger guarantees around internal bookkeeping and failed component renders.
//
// todo!()
if let Some(builder) = render(self) {
let new_head = builder.into_vnode(NodeFactory {
bump: &self.frames.wip_frame().bump,

View file

@ -64,10 +64,10 @@ fn create() {
"Hello, world!"
div {
div {
Fragment {
"hello"
"world"
}
// Fragment {
// "hello"
// "world"
// }
}
}
}
@ -208,20 +208,26 @@ fn create_simple() {
#[test]
fn create_components() {
static App: FC<()> = |(cx, props)| {
cx.render(rsx! {
Child { "abc1" }
Child { "abc2" }
Child { "abc3" }
})
todo!()
// cx.render(rsx! {
// Child { "abc1" }
// Child { "abc2" }
// Child { "abc3" }
// })
};
static Child: FC<()> = |(cx, props)| {
#[derive(Props)]
struct ChildProps<'a> {
children: ScopeChildren<'a>,
}
fn Child<'a>((cx, props): Scope<'a, ChildProps<'a>>) -> Element {
cx.render(rsx! {
h1 {}
div { {cx.children()} }
div { {&props.children} }
p {}
})
};
}
let mut dom = new_dom(App, ());
let mutations = dom.rebuild();

View file

@ -1,6 +1,6 @@
#![allow(unused, non_upper_case_globals)]
use dioxus::{prelude::*, DomEdit, TestDom};
use dioxus::{prelude::*, DomEdit, Mutations, TestDom};
use dioxus_core as dioxus;
use dioxus_core_macro::*;
use dioxus_html as dioxus_elements;