DEV Community 👩‍💻👨‍💻

Cover image for Save scroll state in React when visiting another page
Adi
Adi

Posted on • Updated on

Save scroll state in React when visiting another page

The problem:

Saving scroll state is very important for a good user experience especially when the page in your React web application is really long and has a lot of content. It can be quite annoying when a user visits another page and comes back to the previous page only to find out that they have to scroll from the top of the page all over again. Well we can save them this pain by adding a little code that saves the scroll position of the page the user was at before.

Create two separate functions as follows:

// Object in which we will save our scroll position state
const state = {}

// Function to save the scroll state
export const saveState = (page, object) => {
    state[page] = object
}

// Function to get the scroll position state
export const getState = (page) => {
    return state[page]
}
Enter fullscreen mode Exit fullscreen mode

In the main component where you want to retain the scroll position add the following code:


import {getState, saveState} from "./Util";

// Get stored scroll position state
const scrollPoint = getState('scrollState')
const scrollY = scrollPoint?.scrollY

/* useEffect to get and set the scroll position in the 
current page */
useEffect(() => {
    if (scrollY) {

/* setTimeout used to set the scroll position as the
useEffect triggers before the actual page renders */
        setTimeout(() => {
            window.scrollTo(0, scrollY);
        }, 50)
    }
}, [scrollY])

// useEffect to store the scroll position in the current page 
useEffect(() => {
    const save = () => {
        saveState('scrollState', {
// accessing the vertical scroll position in the window object
            scrollY: window.scrollY
        })
    }

/* Firing the save function whenever the event listener 
picks up a scroll event */
    window.addEventListener('scroll', save)
    return () => window.removeEventListener('scroll', save)

}, [])
Enter fullscreen mode Exit fullscreen mode

You can also use this separately as a custom hook and then use it in every component/page where you intend to save the scroll position. See here in my other article where I use the same logic in a custom hook.

There you go, you have now successfully set the scroll state of your component.

Top comments (2)

Collapse
lukeshiru profile image
Luke Shiru

We can achieve the same thing in a far simpler way, without having to use useEffect in every component that saves scroll position:

// We can have a `useScrollPosition.js` file:

import { useEffect } from "react";

// We have an object to track scroll positions:
const scrollPositions = {};

// We create a simple hook to deal with the logic
// We default the page to the current location, but it can be customized if needed
export const useScrollPosition = (page = location.href) =>
    // Which is just an effect
    useEffect(() => {
        // That retrieves the saved scroll position (if any)
        const pageScrollPosition = scrollPositions[page];

        if (pageScrollPosition !== undefined) {
            // If we have a position saved, let's move the window there...
            globalThis.scrollTo(0, pageScrollPosition);
        }

        // And then when the component is unmounted, we save the scroll position
        // No need to listen to the scroll event and update constantly
        return () => {
            scrollPositions[page] = globalThis.scrollY;
        };
    }, []);

// Then let's say we have a `ExamplePageContainer.jsx`:

// It can use that hook which automatically will do the scroll behavior for them...
export const ExamplePageContainer = () => {
    useScrollPosition();
};
Enter fullscreen mode Exit fullscreen mode

You could also use remix that has that out of the box 🎉

Cheers!

Collapse
renegadedev profile image
Adi Author

This is an even better solution cheers !

Hacktoberfest is happening now!



It is a month-long celebration of open source. For a lot of devs, its their introduction to open source.


Check out the Hacktoberfest tag on DEV to keep up with the latest!