headless-tree
headless-tree copied to clipboard
Focus to next item breaks with dynamic item height
Describe the bug Focus to next item via keyboard breaks, when virtualizer measure item height dynamically.
To Reproduce Focus on the tree item by mouse click. Navigate to the bottom by pressing arrow down until it stop on some item. If you will click by mouse again on any visible item, navigation start works but after the same navigation to the bottom it will break again.
Expected behavior Navigation works well =)
Additional context
- I took BasicVirtualization example from HeadlessTree which works well.
- I look into example of rendering dynamic item height from react-virtual
- I've added this to rendering item. It's
key,refanddata-index.
{virtualizer.getVirtualItems().map((virtualItem) => {
const item = tree.getItems()[virtualItem.index];
return (
<button
{...item.getProps()}
key={virtualItem.key}
data-index={virtualItem.index}
ref={virtualizer.measureElement}
- I've tried to debug and found that in the
hotkeys-featureimplementation, in theonTreeMountmethod,keydownlistener stops firing by some reason. But I can't understand why exactly.
I'm talking about this part of your code:
// keyup is registered on document, because some hotkeys shift
// the focus away from the tree (i.e. search)
// and then we wouldn't get the keyup event nevermore
element.addEventListener('keydown', keydown)
- Chrome 134.0.6998.166
- @headless-tree/[email protected]
Hi, thanks for the report! I can't seem to access the codesandbox, and get a "Devbox not found" error. Can you please see if that sandbox has public access enabled?
Yes, I see, sorry. Now is public
Hi! Maybe you can suggest me what to debug to help you fix that?
Hi, sorry for remaining silent on this. I saw the sandbox and can reproduce the issue, but haven't had time to dig deeper, I'll update you soon on this again.
I guess the cause for the issue is, that by supplying a custom ref to your tree element, you override the ref supplied by the treeItem.getProps(), so some functionality gets lost. It seems to work with this:
const props = item.getProps();
return (
<button
{...props}
key={virtualItem.key}
data-index={virtualItem.index}
ref={(r) => {
virtualizer.measureElement(r);
props.ref(r);
}}
For some reason, calling item.getProps() twice still causes a different issue, so you need to just call it once if you want to use props and the produced ref seperately, I'll look into that as well, but hopefully this is enough for you to get unblocked by this.
Ohh, I see. This solution helped me. Thank you very much!
Happy that this was helpful! I found that the follow up bug I mentioned, was not from calling item.getProps() twice, but rather that item.getProps() may not be called inside a ref callback, since the ref callback will also trigger on unmount and at that time, the item may already not be registered anymore with HT. It works fine otherwise though. I've added a remark on this in the docs on virtualization, and would close this if this fixes your problem.
Yes, Thank you!