DEV Community

Cover image for Storing State on Local Storage in a React Application
uguremirmustafa
uguremirmustafa

Posted on

Storing State on Local Storage in a React Application

Originally posted on my personal blog ➡️ devugur

Let's say we have a value kept in the state in a react application and we want to keep it there even if we refresh the page. The simplest solution is local storage of the browser!

import React, { useState, useEffect } from 'react';

export default function Name() {
  const [name, setName] = useState('');
  const handleChange = (e) => {
    setName(e.target.value);
  };

  return (
    <div>
      <input type="text" onChange={handleChange} value={name} />
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

In the example code, we store the input value in the name variable and we change it by handleChange function. Whenever we refresh it will be gone! We can get the advantage of the useEffect hook and the localStorage of the browser here.

import React, { useState, useEffect } from 'react';

export default function Name() {
  const [name, setName] = useState('');
  const handleChange = (e) => {
    setName(e.target.value);
  };

  useEffect(() => {
    localStorage.setItem('name-state', JSON.stringify(name));
  },[name]);

  return (
    <div>
      <input type="text" onChange={handleChange} value={name} />
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

setItem method takes two parameters: key for the data and the data itself. Now the data is stored on local storage but if we refresh we wouldn't see the state updated with the local data. In order to achieve that we need to add one more useEffect hook to the mix.

import React, { useState, useEffect } from 'react';

export default function Name() {
  const [name, setName] = useState('');
  const handleChange = (e) => {
    setName(e.target.value);
  };
  useEffect(() => {
    const data = localStorage.getItem('name-state');
    if (data) {
      setName(JSON.parse(data));
    }
  }, []);
  useEffect(() => {
    localStorage.setItem('name-state', JSON.stringify(name));
  },[name]);

  return (
    <div>
      <input type="text" onChange={handleChange} value={name} />
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

Notice that we added the last useEffect hook before the previous one so that the local data is available to us before setting it again.

And that's it. Even if you refresh the browser, the state will be persisted.

If you liked the article and would like to support me, you can follow me on Twitter.

Top comments (3)

Collapse
 
link2twenty profile image
Andrew Bone

I made a hook for making this sort of thing easier.

You would just need to do something like.

const [state, setState] = useState();

useEffect(() => {
  const setHandler = (key) => {
    if(key === "state") setState(storage.get("state"));
  }

  storage.on('set', setHandler);

  return () => {
    storage.off('set', setHandler);
  }
})
Enter fullscreen mode Exit fullscreen mode

Which will mean, provided you use the storage context, the state will always be in sync with local/session storage.

Collapse
 
alexanderarce profile image
Alexander Arce • Edited

Why not add the name variable into the useEffect array like so:

useEffect(() => {
    localStorage.setItem('name-state', JSON.stringify(name));
}, [name]);
Enter fullscreen mode Exit fullscreen mode

Then you would only localStorage.setItem if the name is updated, otherwise, if you had another field (surname for example) everytime you update it the localStorage name would be updated.

Collapse
 
uguremirmustafa profile image
uguremirmustafa

That's a good point. As I store just one item, I didn't mind it. I will update it, thanks for the feedback👍