Can you, or should you use localStorage in Redux's initial state?
Asked Answered
L

1

31

For example...

export const user = (state = {
  id: localStorage.getItem('id'),
  name: localStorage.getItem('name'),
  loggedInAt: null
}, action) => {
    case types.LOGIN:
      localStorage.setItem('name', action.payload.user.name);
      localStorage.setItem('id', action.payload.user.id);
      return { ...state, ...action.payload.user }

    default:
      return {  ...state, loggedInAt: Date.now() }
}

That's a scaled down version of what I'm doing, default returns the state from localStorage as expected. However the state of my application is actually blank once I refresh the page.

Lamberto answered 12/4, 2016 at 18:10 Comment(3)
what do you mean should you? ? depending on your application needs.Idonah
@AvraamMavridis if feels like a bad practice somehow.Lamberto
Possible duplicate of Where to write to localStorage in a Redux app?Tabatha
B
47

Redux createStore 2nd param is intended for store initialization:

createStore(reducer, [initialState], [enhancer])

So you can do something like this:

const initialState = {
  id: localStorage.getItem('id'),
  name: localStorage.getItem('name'),
  loggedInAt: null
};

const store = createStore(mainReducer, initialState);

Since reducers should be pure functions (i.e. no side effects) and localStorage.setItem is a side effect, you should avoid saving to localStorage in a reducer.

Instead you can:

store.subscribe(() => {
    const { id, name } = store.getState();

    localStorage.setItem('name', name);
    localStorage.setItem('id', id);
});

This will happen whenever the state changes, so it might affect performance.

Another option is to save the state only when the page is closed (refresh counts) using onBeforeUnload:

window.onbeforeunload = () => {
    const { id, name } = store.getState();

    localStorage.setItem('name', name);
    localStorage.setItem('id', id);
};
Burrows answered 12/4, 2016 at 18:23 Comment(3)
And yet another option is to use something like pouchDB and couchDB with middleware to help keep the store stateless.Jestude
what about writing to localstorage in the action creators? they are allowed to have side effects. also, is reading via localstorage.getItem to load initial state in the reducer parameter as OP describes a side effect?Schematism
You can use localStorage in action creators for granular state saves. Although I would still prefer a central save state that I can tune. Reducer should be pure functions, and adding data from localStorage in the body of the function is a side effect.Burrows

© 2022 - 2024 — McMap. All rights reserved.