Fix adding nodes to nested fragments (#4929)

* Fix adding nodes to nested fragments

* add note about test
This commit is contained in:
Evan Almloff authored and GitHub committed 2025-11-06 15:48:11 -03:00
1 parent 1236296ea6
commit b252dc0620
2 files changed
+83 -3

No files matched your search

+3 -3
View File
@@ -188,10 +188,10 @@ impl VNode {
Some((idx, Placeholder(_) | Text(_))) => { Some((idx, Placeholder(_) | Text(_))) => {
ElementId(dom.get_mounted_dyn_node(mount_id, idx)) ElementId(dom.get_mounted_dyn_node(mount_id, idx))
} }
// The node is a fragment, so we need to find the first element in the fragment // The node is a fragment, so we need to find the last element in the fragment
Some((_, Fragment(children))) => { Some((_, Fragment(children))) => {
let child = children.first().unwrap(); let child = children.last().unwrap();
child.find_first_element(dom) child.find_last_element(dom)
} }
// The node is a component, so we need to find the first element in the component // The node is a component, so we need to find the first element in the component
Some((id, Component(_))) => { Some((id, Component(_))) => {
+80
View File
@@ -509,3 +509,83 @@ fn replace_and_add_items() {
); );
} }
} }
// Simplified regression test for https://github.com/DioxusLabs/dioxus/issues/4924
#[test]
fn nested_unkeyed_lists() {
let mut dom = VirtualDom::new(|| {
let content = if generation() % 2 == 0 {
vec!["5\n6"]
} else {
vec!["1\n2", "3\n4"]
};
rsx! {
for one in &content {
for line in one.lines() {
p { "{line}" }
}
}
}
});
// The list starts with one placeholder
{
let edits = dom.rebuild_to_vec();
assert_eq!(
edits.edits,
[
// load the p tag template
LoadTemplate { index: 0, id: ElementId(1) },
// Create the first text node
CreateTextNode { value: "5".into(), id: ElementId(2) },
// Replace the placeholder inside the p tag with the text node
ReplacePlaceholder { path: &[0], m: 1 },
// load the p tag template
LoadTemplate { index: 0, id: ElementId(3) },
// Create the second text node
CreateTextNode { value: "6".into(), id: ElementId(4) },
// Replace the placeholder inside the p tag with the text node
ReplacePlaceholder { path: &[0], m: 1 },
// Add the text nodes to the root node
AppendChildren { id: ElementId(0), m: 2 }
]
);
}
// DOM state:
// <pre> # Id 1 for if statement
// <p> # Id 2
// "5" # Id 3
// <p> # Id 4
// "6" # Id 5
//
// The diffing engine should add two new elements to the end and modify the first two elements in place
{
dom.mark_dirty(ScopeId::APP);
let edits = dom.render_immediate_to_vec();
assert_eq!(
edits.edits,
[
// load the p tag template
LoadTemplate { index: 0, id: ElementId(5) },
// Create the third text node
CreateTextNode { value: "3".into(), id: ElementId(6) },
// Replace the placeholder inside the p tag with the text node
ReplacePlaceholder { path: &[0], m: 1 },
// load the p tag template
LoadTemplate { index: 0, id: ElementId(7) },
// Create the fourth text node
CreateTextNode { value: "4".into(), id: ElementId(8) },
// Replace the placeholder inside the p tag with the text node
ReplacePlaceholder { path: &[0], m: 1 },
// Insert the text nodes after the second p tag
InsertAfter { id: ElementId(3), m: 2 },
// Set the first text node to "1"
SetText { value: "1".into(), id: ElementId(2) },
// Set the second text node to "2"
SetText { value: "2".into(), id: ElementId(4) }
]
);
}
}