React.js Prevent Scrolling to top after re-rendering

Viewed 1364

This is an expansion on a previous question asking how to prevent scrolling to top after re-rendering by state changed(sorted state)

I coded auto-sorting table with useState and useEffect.

my code on codesandbox is getting random number every 3 seconds from the API Server with 2 different state (A and B states).

And then notate as table by the state with sorted as A-B.

but, On every Re-rendering, window is scrolling to top.

The Problem is, How can I prevent Scrolling to Top?

On previous Question, I tried useLayoutEffect like below.

 useEffect(() => {
    const updatePosition = () => {
      setCurrentScrollY(window.scrollY);
    };
    window.addEventListener("scroll", updatePosition);
    updatePosition();
    return () => window.removeEventListener("scroll", updatePosition);
  }, []);

  useLayoutEffect(() => {
    window.scrollTo(0, currentScrollY);
  }, [commonKey]);

when I use REST API Request on every 3 seconds like above codesandbox codes, It seems work well.

But Websocket that causing continuous state changing make scrolling choppy.

It seems Websocket connection is causing severe state changing so that makes severe re-rendering.

How can I prevent Scrolling to Top on Re-rendering without choppy scrolling?

p.s Sorry for My Poor English.

1 Answers

This is caused by the browser, not React. The entire table is re-rendering. Column widths and heights (especially in the header) are resizing. When window.scrollY > 0, the browser has no point of reference for preserving the scrolling position without it appearing as if the position hasn't changed, because it doesn't know which pixel you're looking at, and therefore doesn't know by how much the distance between what you're looking at and the top of the document has changed. So it does one of the only two things it can do: scroll to the top.

The other thing that the browser could do (but doesn't) is this:

const scrollX = window.scrollX;
const scrollY = window.scrollY;

useLayoutEffect(() => {
  window.scrollTo(scrollX, scrollY);
});

I cleaned up your code a bit and added the above snippet.

Related