Open sknoslo opened 6 months ago
More info, If you change the repeatable component to be pure component (do not own its own state), it works. https://stackblitz.com/edit/vitejs-vite-prtfgs?file=src%2Ffast-repeater.ts
To simplify, we need repeat directive maintainning state with Key, just like vuejs or lit. https://vuejs.org/guide/essentials/list.html#maintaining-state-with-key https://github.com/lit/lit/blob/ff87eb461dfbfa8fd0101a6a9067dcaaa9b49f92/packages/lit-html/src/directives/repeat.ts#L114
This is vital for cases loopping complex components that has its own state, i.e. treeview component with virtualization.
π Feature Request
Add an optional key to the
repeat
directive, so thatrepeat
can map a DOM node to a specific item when updating views. Similar to how React or Lit work. This would be beneficial for a couple of reasons:repeat
can maintain their own internal state.π€ Expected Behavior
When an array is sorted, or items are added or removed, existing DOM nodes should only be reused for an item with the same key. New DOM nodes should be created for keys that did not previously exist, and DOM nodes should be removed for keys that no longer exist. DOM nodes should never be reused for items with different keys.
π― Current Behavior
When an array is sorted, or items are added or removed, existing DOM nodes are reused just based on position, and the nodes do not map 1-to-1 with the array elements.
π Possible Solution
Add a optional key function to the repeat directive. Maintain a map of keys -> DOM nodes, and make updates accordingly. Might look something like:
Adding a separate "keyed repeat" directive could also be a good option if it makes more sense to keep the behavior distinct.
π¦ Context
I was building a notification component that could stack alerts to display for a short time. These elements had
role="alert"
so that a screen reader would announce them when they showed up. But, because nodes are recycled, as new alerts show up or were dismissed, the contents of existing nodes change and the screen reader announces them again, as if they are actually new.I had to fall back to manually managing the DOM instead of using a template with the repeat directive.
π» Examples
Comparison of behavior between Lit and FAST on StackBlitz. This is a contrived example where a parent element renders a list of numbers in a child element, and the color of the child element can be toggled. This toggle state is owned by each child element. If you toggle the first (or last) item in the list, and then reverse the list, you'll see how the behavior differs.