Skip to content

fix(Virtual): rebuild the window when each changes - #82

Open
luccalaz wants to merge 1 commit into
solid-tv:mainfrom
luccalaz:fix/virtual-stale-slice-on-items-change
Open

luccalaz wants to merge 1 commit into
solid-tv:mainfrom
luccalaz:fix/virtual-stale-slice-on-items-change

Conversation

@luccalaz

@luccalaz luccalaz commented Nov 3, 2026

Copy link
Copy Markdown
Contributor

Summary

When each changes but the window's start stays the same, VirtualRow/VirtualColumn keeps the old window items instead of switching to the new ones. This PR rebuilds the window from the new items whenever each changes.

Why

computeSlice only rebuilds the window when start changes (start !== prev.start || newSlice.length === 0). That's fine when items are only appended after the window, but if an item inside or before the window is reordered, removed, or replaced with a new object, the window keeps the old items.

On the next key press the window shifts and is built from the new items. <List> can't match them to the old ones, so it updates the existing nodes in place instead of sliding them over. The focused node stays where it was while selected moves, and the following press puts focus in the hidden slot off-screen. This happens with or without wrap.

Fix

In the items effect, clear the window (slice.slice = noItems) before calling computeSlice. This takes the existing newSlice.length === 0 branch and rebuilds the window from the new items.

This only runs when each changes, and nothing changes in the key press path. The rebuild it triggers would otherwise happen on the next key press anyway.

Tests

Added contract tests in tests/contract-virtual.test.tsx: with scroll="always" + wrap and with scroll="auto", the focused item is moved to the front or removed, then Right is pressed twice. They check that the focused element is the child at selected and that it shows the expected item. All 4 cases fail without the fix and pass with it, and the full suite passes.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant