elgerlambert / redux-localstorage

Store enhancer that syncs (a subset) of your Redux store state to localstorage.
MIT License
1.32k stars 107 forks source link

localStorage values getting cleared when refreshing the page #14

Closed rightaway closed 8 years ago

rightaway commented 8 years ago

I think this just started happening after upgrading to the latest redux and redux-localstorage (was using versions from a few weeks ago previously). When I refresh the page, the values I've set in localStorage get reverted back to the empty {}. Am I doing it wrong, or did something change?

const idLocalStorage = compose(
  filter('main.id')
)(adapter(window.localStorage));

const createStoreWithMiddleware = compose(
  applyMiddleware(thunk),
  persistState(idLocalStorage, 'id'),
  reduxReactRouter({ routes, createHistory }),
  devTools(),
  persistStateDevTools(window.location.href.match(/[?&]debug_session=([^&]+)\b/)),
)(createStore);

function configureStore(initialState) {
  const store = createStoreWithMiddleware(reducer, initialState);
  if (module.hot) {
    // Enable Webpack hot module replacement for reducers
    module.hot.accept('./reducers', () => {
      const nextReducer = require('./reducers');
      store.replaceReducer(nextReducer);
    });
  }
  return store;
}

const store = configureStore();
elgerlambert commented 8 years ago

Hi @rightaway, yes something changed; rehydration of the persisted state isn't done "auto-magically" anymore. There were a number of edge cases that led to unexpected behaviour and it felt too opinionated. You can either use the higher order reducer provided by redux-localstorage ("mergePersistedState") or handle the INIT event in your own reducer(s). Have a look at the Readme on the breaking changes branch for more info: https://github.com/elgerlambert/redux-localstorage/tree/1.0-breaking-changes

rightaway commented 8 years ago

Thank you! The deep merge fix you suggested works beautifully.

localhosted commented 8 years ago

@elgerlambert How to accomplish this merge using the current version? I am having the same issue, but I don't want to use 1.0.

elgerlambert commented 8 years ago

Hi @localhosted, version 0.4 performs a simple shallow merge of your persisted data by default. If your requirements are more complex (e.g. you require a deep merge or you're using immutable data structures for example) than you can pass in your own merge function as follows:

var myMergeFunction = function (initialState, persistedState) {
  // custom merge logic goes here
  return mergedState
}

var createPersistentStore = compose(
  persistState(/*paths*/, {merge: myMergeFunction})
)(createStore)

Note: There is a know issue with 0.4 which is a complication with default/initial values defined in your reducers. The problem in short is this: 0.4 takes the initialState passed in to createStore and merges that with the persisted state. Redux's @@redux/INIT action is dispatched after (this action effectively populates your store with all the default values defined in your reducers). This issue is fixed in 1.0, since @@redux/INIT is called first and the merge happens directly after. For more info you could try and digest issue #2.

Let me know if you're unable to solve your issue with the info above.