React Hooks — keep scroll position during change list views

Mikolaj Kocieda
2 min readJul 19, 2020

--

During working on one of my projects I met an interesting problem. Let’s say you have a list of items which can be shown as a simple grid of items or in the detailed grid as cards with images, description etc, like mocks bellow.

Implementation of this is really simple, the view switch state can be stored in useState hook or even in Redux if it’s needed.

So, where is a problem?

The problem which I met is when you scroll down and then change the view, your scroll position will remain as it was before the change and because of this, you will see different items then was in the previous view. For better understanding — imagine you scroll to Item 5 than you change the view to CARD/details, and you can’t see Item 5, but it will show Item 2 because card items are higher than list items. See example below:

How to solve it?

You can solve this in the following steps:

  1. Before switch check with the item is currently in the view
  2. Store this information
  3. Change view
  4. Check the position of stored item
  5. Change scroll position to the stored item

The main problem is how to call the function before changing view. You can, of course, listen to scroll event and saving item, but it doesn’t have good performance. The perfect way would be to check DOM directly before changing view and WITHOUT changing toggle function.

getSnapshotBeforeUpdate

For a situation like this react prepared lifecycle method called getSnapshotBeforeUpdate. You can read more about this here https://reactjs.org/docs/react-component.html#getsnapshotbeforeupdate

But our aim isn’t refactoring now lists to Class Component. So how about hooks?…

Using hooks - useMemo

After a long time searching how we can do this without class component I found information that useMemo is called before rendering component. Thanks to dependencies array in useMemo you can call the function only when view state change. Combining this with useLayoutEffect which is called AFTER render you can create something like this for pinning scroll to the element currently in view.

Full example

--

--

Mikolaj Kocieda

Full Stack Developer from Poland with experience in React, Node.JS and Go