Focus is lost during list re-order
See original GitHub issue- Check if updating to the latest Preact version resolves the issue (latest is still impacted)
Describe the bug Focus is lost during list re-order. When a list re-renders, if the focused item is moved to later in the source order, it loses focus.
To Reproduce As shown in this Code Sandbox If a list is re-ordered: focus is properly preserved when moving up in the source order, but not down in the source order. (All items have keys that are stable and not indexed based)
Steps to reproduce the behavior:
- Go to the Code Sandbox
- Click on an item in the list
- Move the item up with the up arrow key, and observe the focus remains on the correct item.
- Move the item down with the down arrow key, and observe the focus is lost.
Expected behavior The item should maintain focus no matter which direction in the source order it moves.
Similar issue
This is similar to: Input loses focus when conditionally rerendering other divs #540.
However, since this issue is not about conditional rendering, only list rendering, and because that issue is closed whereas this issue effects the latest tested version (10.5.14
), I believe this warrants it’s own ticket.
Issue Analytics
- State:
- Created 2 years ago
- Comments:5 (1 by maintainers)
Top GitHub Comments
Interesting - this is an unfortunate effect of an optimization Preact does: we “detect” small swap or shift movements within a list of keyed items and only invoke a single
insertBefore()
to move one of the items because we know the other affected item will end up in the correct place as a result. In order for this to work, we always move the first out-of-place item.In your demo, hitting the up arrow key shifts the item up, which means it’s the first out-of-place item in the newly sorted list of items. Conversely, the down arrow key shifts the item down, which means the item it was shifted “around” (the next item in the list) will be the first out-of-place item in the new set of children.
The result is that pressing “up” moves the previous item to after the selected item, whereas pressing “down” moves the selected item to after the next item, which means you lose focus.
We removed manual focus management code from Preact, because it’s really difficult to justify the performance impact. I do think this is an interesting case to explore fixes for (rather than documenting as a difference to React), but we’d be looking for ways of taking focus state into account during diffing rather than any sort of manual focus restoration.
Ahh, I see. I hadn’t clued in that it was just a matter of swapping the other element for the focused one to remain selected.
Given that this does work in React (as you mentioned above, and shown in this React CodeSandbox): Should this issue still be considered a bug for Preact? Either to fix, or to add to the “Differences to React” docs?