virtual icon indicating copy to clipboard operation
virtual copied to clipboard

React 19 issue with useWindowVirtualizer

Open fat opened this issue 1 year ago • 6 comments
trafficstars

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.

fat avatar Jun 27 '24 00:06 fat

same issue here, but droppind a virtualizer in a ref does not helps

Prains avatar Jul 03 '24 12:07 Prains

Running into the same issue. useRef seems to work for now for us.

izakfilmalter avatar Jul 03 '24 19:07 izakfilmalter

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

eqqe avatar Nov 14 '24 14:11 eqqe

+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

cacabo avatar Dec 11 '24 01:12 cacabo

Yep, 'use no memo' seems like a reasonable temporary workaround! 👍

piecyk avatar Dec 12 '24 20:12 piecyk

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

zeorin avatar May 20 '25 15:05 zeorin