Have you ever wondered how to synchronize your component state with local storage? It can be useful to store the state of your application in the browser’s local storage. To retain form data even after a page refresh for example, or to cache data that has been fetched with an API call. In this article, we’ll guide you through writing a simple hook called UseLocalStorage that can be used to store data in local storage.

Before we begin, let’s define the requirements for the hook:

  1. The hook should expose a method to set data.
  2. The hook should return the latest data.
  3. The key on which we store data in local storage should be configurable.

This is the behavior of a default <input /> element:

The simple form field loses input after refresh.

To start, we’ll create a test component that uses the hook to store data entered in an input field. After a browser refresh, the data should still be there.

We can now use the <PersistentInput /> wherever we want. This code should work as expected, but you’ll notice that the input component does not re-render even though the local storage is updated. This is due to React’s rendering principles. Local storage, being an external data source, does not cause the input component to re-render when it is updated. More information on how and when React renders can be found in their documentation.

To make the component more reactive, we need to use the useState hook from React. We’ll update the useLocalStorage function. Start with adding the import statement from React.

And then update the function:

Now, when you test the component, the input should be updated on change and the data should be persisted after a page refresh.

The input field is updated onChange and persisted after the page refreshes.

What about objects?

So far, so good. Often our states are bigger than just one field or a simple type like text or number. How would our hook perform when it has to hold information about multiple input fields? I’ve created a form component to test it.

It appears that our hook fails to deliver what we expect of it. To solve it we’ll have to JSON.stringify the value on storing and JSON.parse it when we fetch it. This is because the window.localStorage.setItem function expects a string value. To comply, we’ll have to serialize our object. More on the serialization of JSON in JavaScript can be found on the mdn docs.

This is what our updated function will look like:

Time for the final demonstration:

We can now use this hook to persist JSON objects to the local storage of the device/browser.

The basics of the hook are now in order! We now have a simple and flexible useLocalStorage hook that to use in your React projects. Of course, you can further improve and expand on it, but it should be a good starting point for most use cases. One potential challenge you might face is handling null or undefined values. Can you identify ways to enhance the hook to handle unexpected states more effectively?

When your application grows you might benefit from using a library optimized for managing large client-side states. An example library that does such a thing is React Query. State management tools are mostly used in medium to large projects. For hobby or smaller projects using the UseLocalStorage hook can be powerful enough.

Tryout the hook yourself in the sandbox below:

Hopefully, you’ve enjoyed reading this article. Don’t hesitate to leave questions or feedback in the comments.

Leave a Reply

Your email address will not be published. Required fields are marked *