All posts

Simplest Custom Hook to Persist Data.

As a React guy I so wanted to make a React hook which I can use for my future projects, taking the advantage of the local storage.

I was recently filling a survey form built on Typeform (Highly recommend using) and I must say that it has an amazing UX compared to it's competitors like Google form, Microsoft form etc. The thing which got me the most hooked was, when I mistakenly closed that tab in-between and reopened it again, all my information filled before was still there. Typeform was persisting data unlike Google forms or other platforms that I have come across.

Typeform was leveraging the local storage API of the browser. So, as a React guy I so wanted to make a React hook which I can use for my future projects, taking the advantage of the local storage.

Custom hook useLocalState

Here we will be using the window.localStorage API and store the data in the local storage of the browser. Even if you close the tab and come back to the same page, your previous state will be preserved.

For this, first we will be using a useState hook with a callback function returning the value from the local storage of the browser if the data is present, Otherwise, the default value passed as a prop.

javascript
const [value, setValue] = useState(() => {
  const tempValue = window.localStorage.getItem(key);
  return tempValue !== null ? JSON.stringify(tempValue) : defaultVal;
});

The data can be saved to the local storage with a specific key assigned to the data. You can think this of as a kind of object as well.

Next we will have to sync the data and update it if it's changed. We will be taking use of the useEffect hook for this.

javascript
useEffect(() => {
  window.localStorage.setItem(key, JSON.stringify(value));
}, [value]);

The custom useLocalStorage hook.

javascript
import { useEffect, useState } from "react";

const useLocalStorage = (defaultVal, key) => {
  const [value, setValue] = useState(() => {
    const tempValue = window.localStorage.getItem(key);
    return tempValue !== null ? JSON.stringify(tempValue) : defaultVal;
  });

  useEffect(() => {
    window.localStorage.setItem(key, JSON.stringify(value));
  }, [value]);

  return [value, setValue];
};

export default useLocalStorage;

Example application

Let's make a simple counter with two function, increment and decrement to understand this concept.

javascript
import React from "react";

const App = () => {
  const [count, setCount] = useLocalState(0, "count");

  const increment = () => {
    setCount(count + 1);
  };

  const decrement = () => {
    setCount(count - 1);
  };

  return (
    <div>
      <h1>Counter:</h1>
      <h2>{count}</h2>
      <button onClick={increment}>Increment (+)</button>
      <button onClick={decrement}>Decrement (-)</button>
    </div>
  );
};

export default App;

Try out this example. Here

NOTE

Do not use this hook in SSR frameworks. The local storage API shows error is SSR frameworks like (Nextjs, Gatsby etc). As it will be compiled on the server side and the local storage of the server will be referenced and not the client's browser.

Thanks for reading.Back to all posts