virtual
virtual copied to clipboard
React 19 issue with useWindowVirtualizer
Describe the bug
Sorry for the drive by issue…
We ran into a problem with react 19 today that was a pita to track down. So dropping it here incase it's useful to anyone.
We had a simple useWindowVirutalizer in a client component in next.js w/ react 19 (like this):
const virtualizer = useWindowVirtualizer({
count: branches.length,
estimateSize: () => 66,
overscan: 5,
scrollMargin: listRef.current?.offsetTop ?? 0,
});
and virtualizerRef.getVirtualItems() was being hoisted / memo'd by the compiler in such a way that it was always returning 0 for getVirutalItems.
To fix it we just dropped the virtualizer in a ref…
const virtualizer = useWindowVirtualizer({
count: branches.length,
estimateSize: () => 66,
overscan: 5,
scrollMargin: listRef.current?.offsetTop ?? 0,
});
// we do this because react 19 was optimzing it away
const virtualizerRef = useRef(virtualizer);
…
virtualizerRef.current.getVirtualItems() // etc…
Your minimal, reproducible example
n/a
Steps to reproduce
Don't have time to spin up a test case sorry!
Expected behavior
Expected getVirtualItems() to return items.
How often does this bug happen?
Every time
Screenshots or Videos
No response
Platform
macos, chrome, react 19
tanstack-virtual version
3.7.0
TypeScript version
No response
Additional context
No response
Terms & Code of Conduct
- [X] I agree to follow this project's Code of Conduct
- [X] I understand that if my bug cannot be reliable reproduced in a debuggable environment, it will probably not be fixed and this issue may even be closed.
same issue here, but droppind a virtualizer in a ref does not helps
Running into the same issue. useRef seems to work for now for us.
It gives me an issue with eslint however.
Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef)eslint(react-compiler/react-compiler)
Edit: it might be removed in a PR https://github.com/facebook/react/pull/30843/files
+1, I am seeing this with:
{
"@tanstack/react-virtual": "^3.11.1",
"react": "^18.3.1",
"react-compiler-runtime": "^19.0.0-beta-63b359f-20241101",
"react-dom": "^18.3.1",
}
Putting a hook in the component after .getVirtualItems appears to be another workaround
Another option is "use no memo"
https://react.dev/learn/react-compiler#something-is-not-working-after-compilation
Yep, 'use no memo' seems like a reasonable temporary workaround! 👍
I work around this with the following hook:
const useNoMemo = <const T>(factory: () => T): T => {
'use no memo';
return factory();
}
which I then use like this:
const virtualItems = useNoMemo(() => virtualizer.getVirtualItems());
This de-opts just the call to virtualizer.getVirtualItems without de-opting the rest of the component.
See https://github.com/facebook/react/issues/33057#issuecomment-2894450792