Finally found the root cause...
Problem:
if you use redux-devtools & call replaceReducer, the initial state overrides the persisted state.
Reason:
replaceReducer doesn't know about the reducerEnhancer that autoRehydrate() creates. That means the devtools inits without it, and doesn't merge the initial state with the persisted state.
Reproduction:
Call store.replaceReducer on an async route. (Probably works on sync routes, too. Haven't tried).
Workarounds:
None (use redux-storage?)
Fix:
Either offer a reducerEnhancer like redux-storage or lift the replaceReducer into the liftedStore. I think the former is cleaner because autoRehydrate does not need a lifted store, so using a higher-level API seems reasonable.
Can you point me to an example of how to lift replaceReducer?
I am hesitant to do a breaking api change of switching to a reducer enhancer.
Do you have an example of a reducerEnhancer @mattkrick ?
I've been battling with this, (And with async injection of reducers) I'd love to submit a PR :)
oh shoot, sorry i let this go dormant.
@rt2zz probably the easiest example I can think of is for something I wrote awhile back: https://github.com/mattkrick/redux-operations/blob/master/src/index.js#L257-L259
@fforres There are, to my knowledge, 3 reducer enhancers in the ecosystem: redux-storage, redux-optimistic-ui, and redux-undo
Ultimately, I went with redux-storage. I certainly can appreciate that breaking changes absolutely suck (going through react 15.2 woes right now 馃槖 ). I also know full well storeEnhancers make for a nicer developer experience than reducerEnhancers, but there's a high price to pay for that convenience, and I've had to defend redux-optimistic-ui from 2 PRs that wanted to do the same thing. For more discussion on the general topic, see https://github.com/mattkrick/redux-optimistic-ui/pull/12, and in the words of our almighty leader Dan: https://github.com/mattkrick/redux-optimistic-ui/pull/8#issuecomment-225016186
@mattkrick thanks for the reference now i understand what you mean by lifted reducer :)
I believe we can classify this as a bug, and fix by lifting the reducer in v3. For v4 I will reconsider the higher order reducer option.
redux-storage is a great choice as well, I am glad that worked out. Redux persist does a lot to be performant out of the box, hopefully after we get all of this sorted you can give it another try 馃憤
I did not come across this issue, has this been fixed?
the latest version now lifts the reducer. I am using it in a HMR environment and it works. If there are outstanding issues please reopen!
@rt2zz I may be misunderstanding something, but I'm not sure this issue is fixed. While it does work in a normal HMR env, it does not work when I am incognito mode and the network is throttled. By the same token, it doesn't work when I deploy my static site.
It seems to me that the reason is that there is a delay in the injection of the async reducer I am using (because of the network) and so the key is not present in the initial Redux state when autoRehydrate is called. Line 68 of autoRehydrate, if (!state.hasOwnProperty(key)) return; makes sure that the injected reducer is not hydrated, although, at least in this case, it should be. By removing this line, everything works as expected (rather as I expected, this may be intended).
Is there a specific reason why this line has to be called (by the way seems to be introduced in this commit)? If not I'll gladly make a PR!
By the way, love the package! Thank you!
Most helpful comment
the latest version now lifts the reducer. I am using it in a HMR environment and it works. If there are outstanding issues please reopen!