-
-
Notifications
You must be signed in to change notification settings - Fork 632
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
<For/> ignores the order of items #533
Comments
I was testing this a bit today and it also doesn't appear to accept duplicates in the new vec either i.e. #[component]
pub fn ForTest(cx: Scope) -> impl IntoView
{
let (list, set_list) = create_signal(cx, vec![1]);
view!{cx,
<ul>
<button on:click=move|_| {
let new_vec = vec![0, 1, 2, 2];
set_list(new_vec);
}>
"Test"
</button>
<For each=list
key=|item|*item
view=move |item| {
view!{cx,
<li>{item}</li>}
}
/>
</ul>
}
} Expected Behavior for me: Actual Behavior: version: 0.2.0-alpha |
Interestingly let (list, set_list) = create_signal(cx, vec![-1]); // note the start is now -1 (a different value than what we will set) And let new_vec = vec![0, 1, 2, 2]; // 1 isn't in the initial vector so this will be [0, 1, 2, 2,] -> [0, 1, 2]
set_list(new_vec); This will now have the correct order but won't have the right amount of elements. Expected Behavior for me: Actual Behavior: version: 0.2.0-alpha |
Ah okay so here's the issue... It's the key... Basically key=|item|*item Is a bad idea because we need the #[component]
pub fn ForTest(cx: Scope) -> impl IntoView
{
let (list, set_list) = create_signal(cx, vec![1]);
view!{cx,
<ul>
<button on:click=move|_| {
let new_vec = vec![0, 1, 2, 2];
// set_list.update(|vec: & mut Vec<i32>| {
// *vec = vec![2, 0, 1, 2, 2];
// });
set_list(new_vec);
}>
"Test"
</button>
<For each=list
key=|_| Uuid::new_v4() // notice that we now generate a unique ID
view=move |item| {
view!{cx,
<li>{item}</li>}
}
/>
</ul>
}
} Will render as expected Expected Behavior for me: Actual Behavior: ✅ version: 0.2.0-alpha |
I'm sorry for the lack of explanation.
In my observation using the below code, it seems to occur when multiple items are inserted to multiple separated places in one update. #[component]
fn ForTest2(cx: Scope) -> impl IntoView
{
let (list, set_list) = create_signal(cx, vec![]);
let (text, set_text) = create_signal(cx, "".to_owned());
let (deduped_text, set_deduped_text) = create_signal(cx, "".to_owned());
let (prev_text, set_prev_text) = create_signal(cx, "".to_owned());
let update = move|_| {
let mut deduped = Vec::new();
let mut seens = HashSet::new();
let mut dedup_node = "".to_string();
for item in text().split_ascii_whitespace() {
if !item.is_empty() {
if seens.insert(item.to_owned()) {
deduped.push(item.to_owned());
} else {
dedup_node = format!(" (deduped from {})", text());
}
}
}
let deduped_text = deduped.join(" ") + &dedup_node;
set_deduped_text(deduped_text);
set_prev_text(list().join(" "));
set_list(deduped);
};
view!{cx,
<ul>
<li>"prev____:" {prev_text}</li>
<li>"expected:" {deduped_text}</li>
<li>"actual__:"
<For each=list
key=|item| item.to_owned() // key is unique String here
view=|cx,item|view!{cx, <span>{item}{" "}</span>} />
</li>
<li>"next___:"
<input on:change=move|e| set_text(event_target_value(&e)) />
<button on:click=update>"update"</button>
</li>
</ul>
}
}
|
Thanks for the detailed report. We're taking a look. This is clearly at least in part a bug in @omie-lol, if you generate unique IDs inside the If it's helpful to unblock your work for now, you can always use a (less-efficient) unkeyed list like this <ul>
{move || list().into_iter()
.map(|item| view!{ cx, <span>{item}{" "}</span>})
.collect::<Vec<_>>()}
</ul> But we'll dig into it. |
Sorry I haven't left an update here in a while. This was an issue specifically involving moving the item at index 1, but it has led @jquesada2016 to work on writing some comprehensive tests for this component and he's in the late stages of an updated algorithm which should resolve this and any similar edge cases. |
Rewrites the algorithm behind the `<For/>` component to create a more robust keyed list implementation, with the potential for future additional optimizations related to grouping moved ranges. Closes leptos-rs#533.
Hi, the following code renders a list of numbers.
Expected Behavior for me:
1 -> push the button -> 0 1 2
Actual Behavior:
1 -> push the button -> 1 0 2
version: 0.2.0-alpha
feature: csr (default)
The text was updated successfully, but these errors were encountered: