Next makes dividing our app into server-side-rendered pages easy. Using the same component on different pages isn't a problem too — but keeping the state is. By default, when opening a different page, the state of the component is reset. Let's look at a small example.
Given this small button component:
We include it in two different pages, accessible to each other via
about.js is basically the same file, so I'll leave you with one snippet.
When putting things together, we notice the following: Incrementing the button works fine. But when switching to the other page, the state is lost. In some apps, this is not what we wish — what we want instead is keeping the state somehow. Here is how to do it easily.
Introducing the session storage
The Web Storage API should be in the toolbox of every developer. It consists of two features for storing data: First, the more popular localStorage, which saves a key-value pair permanently in the browser. Second, the sessionStorage, which saves a key-value pair for the duration of a session. A session? Let me clarify this.
When you open up
youtube.com, your session starts. When you click on a button and navigate to
youtube.com/feed/subscriptions your session still is on. When you close the window, the session is done.
Keeping the state for the duration of a session is a common use case — for example, when you have a search bar and want to keep its input on the results site the user is navigated to.
Hint: There are libraries optimized for persisting states. I only intend to show you how persisting state often works — using the session storage. In most cases, using a library is a better option.
When wanting to keep state across pages, we need to do two things:
Save the current state
Receive the current state from the storage to write it into the React state
Both are great uses cases for React hooks, more precisely, the
useEffect hook. Saving the current state, whenever it is changed, to the sessionStorage is a case for
useEffect listening to a single state. Whenever our counter-state changes, we commit the changes to the session storage:
Fetching the session storage and hydrating the component state with it is a case for the
useEffect configuration that works like
componentDidMount — once the component is mounted.
Yet, this will lead to a small flicker every time we switch the page. Why? Because the code inside
useEffect is getting executed after our component is made visible on the screen.
To avoid this, we can use
useLayoutEffect as it serves as the
useEffect alternative, when the DOM is mutated. Apart from the name, the syntax is almost the same as with
In case the session storage key-value pair does already exist, we copy it's data into the state. In case this entry in the session storage does not exist yet, we create it.
Since it is not all black and white, there is a disadvantage of
useLayoutEffect: Compared to the classic
useEffect, its alternative delays the browser painting. Yet, in our case, this isn't much of a problem in this case.
Putting it all together:
When we now increase the button and switch the pages, the state will be kept — since using
useLayoutEffect it is a smooth transition, without a flicker when hydrating the state.
Thank you for reading!