virtual icon indicating copy to clipboard operation
virtual copied to clipboard

React Compiler: useVirtual results are cached at their initial values

Open gdorsi opened this issue 1 year ago • 8 comments

Describe the bug

An usage of useVirtual gets compiled by React Compiler into something like this:

const virtualizer = (0,
_tanstack_react_virtual__WEBPACK_IMPORTED_MODULE_9__.useVirtualizer)(t3);
let t4;
if ($[9] !== virtualizer) {
  t4 = virtualizer.getVirtualItems();
  $[9] = virtualizer;
  $[10] = t4;
} else {
  t4 = $[10];
}

Since the virtualizer ref never changes, the virtual items never get updated.

Not sure if this should be a Tanstack Virtual issue or React Compiler needs to apply less assumptions when caching values, but thought that would be good to flag the problem here.

Wrapping useVirtual into something like this fixes the issue:

const useVirtualWrapper = (...args) => {
  'use no memo';
  return { ...useVirtual(...args) };
}

Your minimal, reproducible example

https://codesandbox.io/p/devbox/runtime-dew-9rlvm7

Steps to reproduce

  1. Open the example (forked from https://tanstack.com/virtual/latest/docs/framework/react/examples/fixed)
  2. The virtual lists are rendering no items

Expected behavior

The UI should be the same as https://tanstack.com/virtual/latest/docs/framework/react/examples/fixed

How often does this bug happen?

Every time

Screenshots or Videos

No response

Platform

  • MacOS, Chrome and Firefox

tanstack-virtual version

3.5.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.

gdorsi avatar May 23 '24 17:05 gdorsi

Similar thing happens if the component is wrapped in memo. @tannerlinsley this error only shows up with strict mode off (i.e. in production).

relsunkaev avatar Jun 15 '24 19:06 relsunkaev

Specifying initialRect made it work for me

relsunkaev avatar Jun 15 '24 19:06 relsunkaev

got same problem, very annoying when using react-compiler. My workaround was to save an instance of virtualizer as state when the onChange function is saved, and use that instance in my component instead of the instance returned by the hook.

    const [virtualizer, setVirtualizer] = useState<Virtualizer<HTMLDivElement, Element> | null>(null);

    useVirtualizer({
        count: data.getCount(),
        estimateSize: () => 30,
        getScrollElement: () => scrollableRef.current,
        onChange: (i) => setVirtualizer(i),
    });

   ....
    <>
       virtualizer?.getVirtualItems().map(v => {
          ....
       }
    </>

any official solution or hint?

nicolo-danzi-one avatar Jul 31 '24 10:07 nicolo-danzi-one

'use no memo' seems like a reasonable temporary workaround! https://react.dev/learn/react-compiler#something-is-not-working-after-compilation

piecyk avatar Dec 12 '24 20:12 piecyk

Specifying initialRect made it work for me

Can you show how exactly did you get it?

Grawl avatar Dec 19 '24 09:12 Grawl

export default function VirtualList() {
  // opt out of react compiler
  'use no memo';
}

this works for me

GrahamQuan avatar Mar 09 '25 09:03 GrahamQuan