Saving Redux State to Local Storage


In this video we are going to look at problem that is inherent in any Redux project, which is that by default, your application's state will not persist past a browser refresh.

To remedy this, we will save our application's local representation of state to localStorage.

By using localStorage, our locally saved state will survive even if the browser window is closed. If you'd rather only keep data alive as long as the browser window is kept open then sessionStorage may be the way to go. The API is identical.

This is a tip I learned from this excellent video from Dan Abramov.

With the way in which this works, you could adapt the following two functions to any sort of storage you like. For every similar problem I've ever had, localStorage has been perfectly fine.

localStorage acts a key / value store. This means we need a key, and a value to write. And a key to read.

You won't need to do any import statements to make this work.

Let's see the code:

// /src/connectivity/localStorage.js

export const loadState = () => {
  try {
    const serializedState = localStorage.getItem('state');

    if (serializedState === null) {
      return undefined;
    }

    return JSON.parse(serializedState);

  } catch (err) {
    return undefined;
  }
};

export const saveState = (state) => {
  try {
    const serializedState = JSON.stringify(state);
    localStorage.setItem('state', serializedState);
  } catch (err) {
    // die
  }
};

As our state is a plain old JavaScript object, we can serialize (JSON.stringify) and deserialize it (JSON.parse) as required.

By subscribing the saveState functionality to our Redux store, we can ensure this function will be called any time our state is updated. It's a lovely, clean separation of concerns.

/src/store/configureStore.js

  store.subscribe(() => {
    saveState({
      auth: store.getState().auth
    });
  }));

However, as our application's state may be changing frequently, we likely don't need to write every single change to localStorage, which would be costly.

By wrapping the function in lodash's throttle we can ensure this method will be called at most, once per second (1000 ms) in our example:

/src/store/configureStore.js

import _ from 'lodash';

// * snip *

  store.subscribe(_.throttle(() => {
    saveState({
      auth: store.getState().auth
    });
  }, 1000));

Nice.

Code For This Course

Get the code for this course.

Code For This Video

Get the code for this video.

Episodes