3

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.

reaver lover
  • 624
  • 7
  • 20
  • I noticed that entire data in table is modified after every three seconds, whenever there is a complete data change in table, it's better to have scroll bar located at top. But if you want to position the scroll bar at previous location, follow this article, it will work. https://dev.to/n8tb1t/tracking-scroll-position-with-react-hooks-3bbj – B.Anup Feb 01 '22 at 06:25

1 Answers1

5

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.

Steve
  • 8,066
  • 11
  • 70
  • 112
  • Example codes like REST API with 3 seconds Interval is ok with your solution. but, Still choppy on Scrolling with WebSocket that causing many state changes.. – reaver lover Feb 02 '22 at 08:04
  • It seems even H/W environment is another cause. Scrolling is not choppy on my M1 mac but window10 still choppy. – reaver lover Feb 03 '22 at 07:17