Autoplay

    Store Values in localStorage with the React useEffect Hook

    Kent C. DoddsKent C. Dodds

    React 16.7.0-alpha.0 was recently released and with it comes a set of experimental hooks and features. Use these with caution as they are likely to change in the near future.

    When you refresh the page in JavaScript, it will clear values that you possibly want to be persisted if you don't store it somewhere as in localStorage.

    Storing something in localStorage is a side effect and in React 16.6 you can utilize useEffect to deal with exactly this type of situation. In this lesson, we'll use useEffect to set a state variable in state whenever state is updated.

    We'll also look at some optimizations available to us with useEffect so we don't have it running every time the component renders.

    reactReact
    Code

    Code

    Become a Member to view code

    You must be a Member to view code

    Access all courses and lessons, track your progress, gain confidence and expertise.

    Become a Member
    and unlock code for this lesson
    Transcript

    Transcript

    Instructor: 00:00 I can click on this counter. That increments the count. When I refresh the page though, it's going to go back to zero. I want it to preserve that state somewhere in localStorage or something so that I can refresh the page and it will restore my count to what it was before.

    00:14 Storing something in localStorage is a side effect. That's exactly what I'm going to use from React. I'll use useEffect. Every time this render function runs, I want to have this useEffect run so I can set the count in localStorage.

    00:28 We'll say, "window.localStorage.setItem count count." Now if I go in here to my dev tools, we'll go over to application and localStorage. We're going to see the count right there. If I increment it, every single time I click, that count is going to get updated.

    00:47 If I refresh now, it actually gets reset to zero. That's because when this counter runs, it's initializing our count to zero. Right here, it's that first argument to useState. When this effect runs, that count value is zero.

    01:00 We need to initialize our state to the count value that is in our localStorage. Let's go ahead and do that. We'll get our initial count from window.localStorage.getItem count. That value could be null or undefined. We'll go ahead and say, "Or zero."

    01:19 Items in localStorage are actually a string. Let's go ahead and and pass that to the number constructor. Now we can pass that initial count to our useState. If I save that, I'll increment it a couple times. We refresh. It stays at four.

    01:32 There are two optimizations I want to make here. The first is every single time that this render method runs, we're going to be reading into localStorage. That could be a performance problem. It's definitely not optimal.

    01:43 What we can do in our useState is we can actually pass it a function which it will only call on the first render. If I change this to a function that returns a read of localStorage count and that function will only be run when this counter is rendered for the first time.

    01:58 The other optimization that we should make here is around the useEffect hook. This useEffect callback is going to be called after every single time our component rerenders.

    02:07 That works fine in our little application here, but there are many reasons that a counter could rerender. We only really care to update localStorage when the count changes specifically.

    02:16 If this counter is rerendered for any other reason, we don't need to update the count in localStorage. Effectively, we only want this callback to be run when the count value changes. The useEffect hook allows us to do this by passing an array as a second argument.

    02:31 If we pass count here, React will only run our callback when the count value changes. We'll save that. Now we have the functionality that we're looking for.

    02:43 In review, what we had to do to make this work is we imported useEffect from React. Then we used that useEffect hook to create a callback function that we want to have run after every time our component renders to set the localStorage value of count to the current state of count for our counter.

    02:58 We made that dependent on the count changing so that this callback only runs when the count is changed. Then we also initialized our state with this initial count, which we read from localStorage. We made that a function so that this code only runs when the counter is rendered initially.

    Discuss

    Discuss