diff --git a/docs/guide/examples/readme_expanded.rs b/docs/guide/examples/readme_expanded.rs index 1ec30e57b..5e09aee56 100644 --- a/docs/guide/examples/readme_expanded.rs +++ b/docs/guide/examples/readme_expanded.rs @@ -85,7 +85,7 @@ fn app(cx: Scope) -> Element { }; // The VNode is a reference to the template with the dynamic parts of the rsx ::dioxus::core::VNode { - parent: None, + parent: Default::default(), key: None, // The static template this node will use. The template is stored in a Cell so it can be replaced with a new template when hot rsx reloading is enabled template: std::cell::Cell::new(TEMPLATE), diff --git a/packages/core/src/create.rs b/packages/core/src/create.rs index e89942f36..a85d977e0 100644 --- a/packages/core/src/create.rs +++ b/packages/core/src/create.rs @@ -192,7 +192,15 @@ impl<'b> VirtualDom { }; self.create_dynamic_node(template_ref, node) } - Placeholder(VPlaceholder { id }) => { + Placeholder(VPlaceholder { id, parent }) => { + let template_ref = ElementRef { + path: ElementPath { + path: &template.template.get().node_paths[idx], + }, + template: &template, + scope: self.runtime.current_scope_id().unwrap_or(ScopeId(0)), + }; + parent.set(Some(self.next_element_ref(template_ref))); let id = self.set_slot(id); self.mutations.push(CreatePlaceholder { id }); 1 @@ -510,6 +518,9 @@ impl<'b> VirtualDom { // Make sure the text node is assigned to the correct element placeholder.id.set(Some(id)); + // Assign the placeholder's parent + placeholder.parent.set(Some(self.next_element_ref(parent))); + // Assign the ID to the existing node in the template self.mutations.push(AssignId { path: &parent.path.path[1..], @@ -538,7 +549,7 @@ impl<'b> VirtualDom { self.assign_boundary_ref(parent, t); self.create_scope(scope, t) } - Aborted(t) => self.mount_aborted(t), + Aborted(t) => self.mount_aborted(t, parent), } } @@ -554,10 +565,18 @@ impl<'b> VirtualDom { .unwrap_or_else(|| component.scope.get().unwrap()) } - fn mount_aborted(&mut self, placeholder: &VPlaceholder) -> usize { + fn mount_aborted( + &mut self, + placeholder: &VPlaceholder, + parent: Option>, + ) -> usize { let id = self.next_element(); self.mutations.push(Mutation::CreatePlaceholder { id }); placeholder.id.set(Some(id)); + placeholder + .parent + .set(parent.map(|parent| self.next_element_ref(parent))); + 1 } diff --git a/packages/core/src/diff.rs b/packages/core/src/diff.rs index 29a135be6..5e015dbb3 100644 --- a/packages/core/src/diff.rs +++ b/packages/core/src/diff.rs @@ -42,11 +42,18 @@ impl<'b> VirtualDom { (Ready(l), Aborted(p)) => self.diff_ok_to_err(l, p), // Just move over the placeholder - (Aborted(l), Aborted(r)) => r.id.set(l.id.get()), + (Aborted(l), Aborted(r)) => { + r.id.set(l.id.get()); + r.parent.set(l.parent.get()) + } // Placeholder becomes something // We should also clear the error now - (Aborted(l), Ready(r)) => self.replace_placeholder(l, [r], todo!()), + (Aborted(l), Ready(r)) => self.replace_placeholder( + l, + [r], + self.element_refs[l.parent.get().expect("root should not be none").0], + ), }; } self.runtime.scope_stack.borrow_mut().pop(); @@ -55,6 +62,7 @@ impl<'b> VirtualDom { fn diff_ok_to_err(&mut self, l: &'b VNode<'b>, p: &'b VPlaceholder) { let id = self.next_element(); p.id.set(Some(id)); + p.parent.set(l.parent.get()); self.mutations.push(Mutation::CreatePlaceholder { id }); let pre_edits = self.mutations.edits.len(); @@ -164,10 +172,13 @@ impl<'b> VirtualDom { match (left_node, right_node) { (Text(left), Text(right)) => self.diff_vtext(left, right), (Fragment(left), Fragment(right)) => self.diff_non_empty_fragment(left, right, parent), - (Placeholder(left), Placeholder(right)) => right.id.set(left.id.get()), + (Placeholder(left), Placeholder(right)) => { + right.id.set(left.id.get()); + right.parent.set(left.parent.get()) + }, (Component(left), Component(right)) => self.diff_vcomponent(left, right, Some(parent)), (Placeholder(left), Fragment(right)) => self.replace_placeholder(left, *right, parent), - (Fragment(left), Placeholder(right)) => self.node_to_placeholder(left, right), + (Fragment(left), Placeholder(right)) => self.node_to_placeholder(left, right, parent), _ => todo!("This is an usual custom case for dynamic nodes. We don't know how to handle it yet."), }; } @@ -838,11 +849,17 @@ impl<'b> VirtualDom { }; } - fn node_to_placeholder(&mut self, l: &'b [VNode<'b>], r: &'b VPlaceholder) { + fn node_to_placeholder( + &mut self, + l: &'b [VNode<'b>], + r: &'b VPlaceholder, + parent: ElementRef<'b>, + ) { // Create the placeholder first, ensuring we get a dedicated ID for the placeholder let placeholder = self.next_element(); r.id.set(Some(placeholder)); + r.parent.set(Some(self.next_element_ref(parent))); self.mutations .push(Mutation::CreatePlaceholder { id: placeholder }); diff --git a/packages/core/src/nodes.rs b/packages/core/src/nodes.rs index 9232b2961..1cf15a28c 100644 --- a/packages/core/src/nodes.rs +++ b/packages/core/src/nodes.rs @@ -373,6 +373,8 @@ impl<'a> VText<'a> { pub struct VPlaceholder { /// The ID of this node in the real DOM pub(crate) id: Cell>, + /// The parent of this node + pub(crate) parent: Cell>, } impl VPlaceholder { diff --git a/packages/fullstack/src/hooks/server_cached.rs b/packages/fullstack/src/hooks/server_cached.rs index 80bb93008..ef2546762 100644 --- a/packages/fullstack/src/hooks/server_cached.rs +++ b/packages/fullstack/src/hooks/server_cached.rs @@ -12,9 +12,10 @@ use serde::{de::DeserializeOwned, Serialize}; /// use dioxus_fullstack::prelude::*; /// /// fn app(cx: Scope) -> Element { -/// let state1 = use_state(cx, || from_server(|| { +/// let state1 = use_state(cx, || server_cached(|| { /// 1234 /// })); +/// todo!() /// } /// ``` pub fn server_cached(server_fn: impl Fn() -> O) -> O { diff --git a/packages/native-core/tests/fuzzing.rs b/packages/native-core/tests/fuzzing.rs index 4f0a34b70..82794e7d0 100644 --- a/packages/native-core/tests/fuzzing.rs +++ b/packages/native-core/tests/fuzzing.rs @@ -255,7 +255,7 @@ fn create_random_element(cx: Scope) -> Element { println!("{template:#?}"); let node = VNode { key: None, - parent: None, + parent: Default::default(), template: Cell::new(template), root_ids: dioxus::core::exports::bumpalo::collections::Vec::new_in(cx.bump()) .into(),