Skip to content

fix: tag tree virtualizer re-measure and scroll-to-selected#179

Open
bk-ty wants to merge 1 commit intokenforthewin:mainfrom
bk-ty:fix/tag-tree-scroll
Open

fix: tag tree virtualizer re-measure and scroll-to-selected#179
bk-ty wants to merge 1 commit intokenforthewin:mainfrom
bk-ty:fix/tag-tree-scroll

Conversation

@bk-ty
Copy link
Copy Markdown
Contributor

@bk-ty bk-ty commented Apr 30, 2026

Problem

Two related issues with the TagTree virtualizer after expand/collapse:

1. Stale height after expand/collapse

Expanding or collapsing a tag node changed flatTags length, but the virtualizer did not remeasure. The scroll area reported the wrong total height until an unrelated re-render happened to trigger a measure, causing visible layout jumps.

2. Scroll-to-selected uses stale tagIndexMap

The scroll effect captured tagIndexMap at mount time. When a tag was first selected, the effect fired with the initial (often incomplete) map rather than the current one, scrolling to index 0 instead of the correct target.

Fix

  • Add a useEffect on [flatTags, virtualizer] that calls virtualizer.measure() whenever the tree structure changes
  • Add tagIndexMapRef — updated on every render outside any effect — so the scroll effect always reads the current map without needing tagIndexMap as a dependency (which would create spurious re-fires on every map mutation)

Testing

  • npx tsc --noEmit — clean

Two issues with the tag tree virtualizer after expand/collapse:

1. Expand/collapse changed flatTags length but the virtualizer did not
   remeasure, causing the scroll area to show the wrong total height
   until the next unrelated re-render. Added a useEffect on flatTags
   and virtualizer that calls virtualizer.measure() when the tree
   structure changes.

2. The scroll-to-selected effect read tagIndexMap via the closure's
   stale capture rather than the latest value at fire time, so the
   first render after a tag became selected would scroll to index 0
   instead of the target tag. Added tagIndexMapRef (updated on every
   render) so the effect always reads the current map without needing
   tagIndexMap as a dependency (which would create spurious re-fires).
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