mirror of
https://github.com/DioxusLabs/dioxus
synced 2024-11-10 06:34:20 +00:00
Fix diffing Option<String> (#2746)
This commit is contained in:
parent
115cc0ad42
commit
33f3d40a49
3 changed files with 101 additions and 3 deletions
|
@ -44,11 +44,20 @@ impl VirtualDom {
|
|||
) {
|
||||
let m = self.create_children(to.as_deref_mut(), r, parent);
|
||||
if let Some(to) = to {
|
||||
to.replace_node_with(placeholder_id, m);
|
||||
self.reclaim(placeholder_id);
|
||||
self.replace_placeholder_with_nodes_on_stack(to, placeholder_id, m)
|
||||
}
|
||||
}
|
||||
|
||||
fn replace_placeholder_with_nodes_on_stack(
|
||||
&mut self,
|
||||
to: &mut impl WriteMutations,
|
||||
placeholder_id: ElementId,
|
||||
m: usize,
|
||||
) {
|
||||
to.replace_node_with(placeholder_id, m);
|
||||
self.reclaim(placeholder_id);
|
||||
}
|
||||
|
||||
fn nodes_to_placeholder(
|
||||
&mut self,
|
||||
mut to: Option<&mut impl WriteMutations>,
|
||||
|
|
|
@ -84,6 +84,12 @@ impl VNode {
|
|||
self.diff_vtext(to, mount, idx, old, new)
|
||||
}
|
||||
},
|
||||
(Text(_), Placeholder(_)) => {
|
||||
self.replace_text_with_placeholder(to, mount, idx, dom)
|
||||
},
|
||||
(Placeholder(_), Text(new)) => {
|
||||
self.replace_placeholder_with_text(to, mount, idx, new, dom)
|
||||
},
|
||||
(Placeholder(_), Placeholder(_)) => {},
|
||||
(Fragment(old), Fragment(new)) => dom.diff_non_empty_fragment(to, old, new, Some(self.reference_to_dynamic_node(mount, idx))),
|
||||
(Component(old), Component(new)) => {
|
||||
|
@ -100,6 +106,42 @@ impl VNode {
|
|||
};
|
||||
}
|
||||
|
||||
/// Replace a text node with a placeholder node
|
||||
pub(crate) fn replace_text_with_placeholder(
|
||||
&self,
|
||||
to: Option<&mut impl WriteMutations>,
|
||||
mount: MountId,
|
||||
idx: usize,
|
||||
dom: &mut VirtualDom,
|
||||
) {
|
||||
if let Some(to) = to {
|
||||
// Grab the text element id from the mount and replace it with a new placeholder
|
||||
let text_id = ElementId(dom.mounts[mount.0].mounted_dynamic_nodes[idx]);
|
||||
let (id, _) = self.create_dynamic_node_with_path(mount, idx, dom);
|
||||
to.create_placeholder(id);
|
||||
to.replace_node_with(text_id, 1);
|
||||
dom.reclaim(text_id);
|
||||
}
|
||||
}
|
||||
|
||||
/// Replace a placeholder node with a text node
|
||||
pub(crate) fn replace_placeholder_with_text(
|
||||
&self,
|
||||
to: Option<&mut impl WriteMutations>,
|
||||
mount: MountId,
|
||||
idx: usize,
|
||||
new: &VText,
|
||||
dom: &mut VirtualDom,
|
||||
) {
|
||||
if let Some(to) = to {
|
||||
// Grab the placeholder id from the mount and replace it with a new text node
|
||||
let placeholder_id = ElementId(dom.mounts[mount.0].mounted_dynamic_nodes[idx]);
|
||||
let (new_id, _) = self.create_dynamic_node_with_path(mount, idx, dom);
|
||||
to.create_text_node(&new.value, new_id);
|
||||
dom.replace_placeholder_with_nodes_on_stack(to, placeholder_id, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/// Try to get the dynamic node and its index for a root node
|
||||
pub(crate) fn get_dynamic_root_node_and_id(
|
||||
&self,
|
||||
|
@ -880,7 +922,7 @@ impl VNode {
|
|||
) -> usize {
|
||||
let (id, path) = self.create_dynamic_node_with_path(mount, idx, dom);
|
||||
|
||||
// If this is a root node, the path is empty and we need to create a new text node
|
||||
// If this is a root node, the path is empty and we need to create a new placeholder node
|
||||
if path.is_empty() {
|
||||
to.create_placeholder(id);
|
||||
// We create one node on the stack
|
||||
|
|
47
packages/core/tests/diff_dynamic_node.rs
Normal file
47
packages/core/tests/diff_dynamic_node.rs
Normal file
|
@ -0,0 +1,47 @@
|
|||
use dioxus::dioxus_core::{ElementId, Mutation::*};
|
||||
use dioxus::prelude::*;
|
||||
use pretty_assertions::assert_eq;
|
||||
|
||||
#[test]
|
||||
fn toggle_option_text() {
|
||||
let mut dom = VirtualDom::new(|| {
|
||||
let gen = generation();
|
||||
let text = if gen % 2 != 0 { Some("hello") } else { None };
|
||||
|
||||
rsx! {
|
||||
div {
|
||||
{text}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// load the div and then assign the None as a placeholder
|
||||
assert_eq!(
|
||||
dom.rebuild_to_vec().sanitize().edits,
|
||||
[
|
||||
LoadTemplate { name: "template", index: 0, id: ElementId(1,) },
|
||||
AssignId { path: &[0], id: ElementId(2,) },
|
||||
AppendChildren { id: ElementId(0), m: 1 },
|
||||
]
|
||||
);
|
||||
|
||||
// Rendering again should replace the placeholder with an text node
|
||||
dom.mark_dirty(ScopeId::APP);
|
||||
assert_eq!(
|
||||
dom.render_immediate_to_vec().sanitize().edits,
|
||||
[
|
||||
CreateTextNode { value: "hello".to_string(), id: ElementId(3,) },
|
||||
ReplaceWith { id: ElementId(2,), m: 1 },
|
||||
]
|
||||
);
|
||||
|
||||
// Rendering again should replace the placeholder with an text node
|
||||
dom.mark_dirty(ScopeId::APP);
|
||||
assert_eq!(
|
||||
dom.render_immediate_to_vec().sanitize().edits,
|
||||
[
|
||||
CreatePlaceholder { id: ElementId(2,) },
|
||||
ReplaceWith { id: ElementId(3,), m: 1 },
|
||||
]
|
||||
);
|
||||
}
|
Loading…
Reference in a new issue