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
Issue with unkeyed VDOM list items #479
Comments
@sirrodgepodge this would be a great feature to have! Would you like to take stab at implementing it? |
thank you @jstarry, would absolutely love to, pretty slammed in the day job now so don't want to promise anything, if no one else does it someday I will though :) |
Would love to invest time on this 🙂 @jstarry would love to get some guidance if possible |
@jeremyscatigna Great, this is a good task to get your feet wet. You're mostly going to be digging into 2 areas of the code base. The macro and virtual dom diffing parts. I think we only need keyed elements inside "list" nodes. The virtual dom list node code is here. You'll need to make changes to As for keyed elements, I think any element could be keyed. So maybe we need a trait for The macro code is split up for components vs tags.. Component: html! {
<MyComponent key={1} />
} Macro code for parsing component properties (we already have special handling for Tag: html! {
<li key={1} />
} Macro code for parsing tag attributes: https://github.com/yewstack/yew/blob/master/crates/macro/src/html_tree/html_tag/tag_attributes.rs Another thing to consider is that we may wish to enforce that keys are used whenever rendering inside lists. I think we can punt that for v2. |
@jstarry do you mean that we need keys within Presumably in general keys can be any Do we need to allow the user to specify if keys are require, absent, or optional in a given context? This feels like a lot of cognitive overhead. But the alternative is that we always have |
Hmm, good question. I don't like the look of
I think we should use string keys to avoid that. So
Yeah this is more in line with what I am imagining. How about optional by default? I'm not sure how required keys would work at all yet. Might have to be a runtime check rather than compile time. |
@jeremyscatigna another thing to consider is that we will likely need keyed lists for this change too. Analogous to React keyed fragments |
@jeremyscatigna whats your status? I would consider picking this up, it's a great opportunity to get into writing macros and I think this feature is important for yew :) |
Hi I implemented a very rough implementation of key to components, If no one is working on it I can try to polish and optimize it (by using hashmaps i suppose) and convert to a PR key can be used on either tag or component { for self.state.terminals.iter().map(|tab| {
html! {
<div key=tab.1.title.clone() class={
if tab.1.is_active{
""
}else{
"is-hidden"
}
}>
<TerminalComp termid=tab.1.title.clone()/>
</div>
}
})
} |
@deep-gaurav I took a look at your changes and they look pretty great! I would love if you opened a PR for it :) |
@jstarry Currently in my implementation for VDiff for every element in Vlist children a linear search is made for same key in ancestor's children, this can be very expensive for list with many children i think. this way the unkeyed children will be in vec with key String::default(), and can be handled same way as before, and keyed children can be accessed directly with their key? |
Hm, it's important to keep the order of list children. Maybe a new data structure can be added with a map of key to children index? |
… a key on the nodes to not process the list. Issue yewstack#479
@jstarry @deep-gaurav I made some changes to use a hashmap. I was wondering though if keyed should be Option instead of String on the nodes? |
Switched to using remove instead of get_mut() to make it so we don't need to do a full scan. Issue yewstack#479
I was able to update the code to default to none on nodes without a key attribute. |
Nodes with keys are in a hashmap and nodes without are in vector. Added an error if duplicate keys are in the hashmap and outputs the duplicate key. Issue yewstack#479
* Add keys to components * Switched to HashMap for added performance. Fixed issue if their isn't a key on the nodes to not process the list. Issue #479 * Ran cargo fmt. * Deleted the node since we don't need it. Switched to using remove instead of get_mut() to make it so we don't need to do a full scan. Issue #479 * Changed the key data type to Option<String>. Issue #479. * Removed rls config file. * Fixed macro test to add the additional VChild parameter. * Updated the code to handle cases where the root has a key. Nodes with keys are in a hashmap and nodes without are in vector. Added an error if duplicate keys are in the hashmap and outputs the duplicate key. Issue #479 * Updated vlist to have key() attribute. Issue #479 * Updated vlist without a key. * Added a user defined key to vlist. * Removed logging statement. * Made the changes requested. Still need to add macro tests. * Updated the macro tests when the syntax changes. * Ran cargo fmt. * Switched to returning a reference for the key. Removed the key comparision for vtag. * Fixed clippy warning. * Switch to use == to do the comparision to fix clippy error. * Add clippy ignore Co-authored-by: Deep Gaurav <deepgauravraj@gmail.com> Co-authored-by: Justin Starry <justin.starry@icloud.com>
Yes it is, thanks! |
Description
First, I'm new to Rust and a project in Yew has been my path to learning since I know JS front development pretty well already, super grateful that this project exists, thank you!
On to the question, in React there's a concept of the "key" attribute for items in lists which allow a user to add a unique ID to list items.
This ensures that nodes in lists can be properly tracked, since order alone is not enough. I see no equivalent here in Yew and sure enough if I remove a list item from the middle of the list, the DOM node at the end of the list is removed and the content from the subsequent list nodes all gets shifted up into the node one above them (as opposed to the node that I actually removed getting destroyed and the subsequent content all staying in the same place).
Expected Results
When item in the middle of the list is removed, remove the corresponding DOM node, don't alter subsequent DOM nodes in list.
Actual Results
When VDOM node from the middle of the list is removed, in the actual DOM a node is removed from the end of the list and all the content that was in nodes following the removed VDOM node gets shifted up by one.
Context (Environment)
The text was updated successfully, but these errors were encountered: