Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue with rehydrate on v3 #87

Closed
felipemartim opened this issue May 5, 2016 · 5 comments
Closed

Issue with rehydrate on v3 #87

felipemartim opened this issue May 5, 2016 · 5 comments

Comments

@felipemartim
Copy link

felipemartim commented May 5, 2016

I'm having a problem regarding the new version of redux-persist that may be very specific to the project I'm working on right now, but, nevertheless, I'll describe it here.

I have a logout action that resets all reducers to the initial state and I'm also using autoRehydrate to load the previous state stored in AsyncStorage (it's a react native app). The issue happens when I open the app, get the state rehydrated and I try to logout immediately after that. The state is never persisted.

By calling "persistStore", the "createPersistor" function is invoked and a new persistor is created with its lastState set to the initial state. The persistor is then paused, which is resumed only after rehydration. That means the "lastState" on the persistor is still the initial state, even after rehydration. When I dispatch my logout action, the new state is compared to the "lastState" and as both are the same, nothing gets persisted in AsyncStorage. If I reload the app the state is still the same before I logged out.

I don't know if this is the intended behaviour or if it's a bug. Is there any reason why the persistor needs to get paused during rehydration?

@rt2zz
Copy link
Owner

rt2zz commented May 5, 2016

persistor is paused until getStoredState is complete otherwise there could potentially be a race condition where state is stored via the persistor before the old state is retrieved, thus overwriting the state that was intended for rehydration.

Your particular case is pretty interesting, we should definitely account for it. One option which I have no fully considered the consequences of would be to set lastState to be the value of the restoredState. This would presumably need to be done when resume() is called.

As a short term workaround you might consider cloning your initialState on logout, so instead of

myReducer (state = initialState, action) {
// ... old way
case 'LOGOUT'
  return initialState

// ... new way
case 'LOGOUT'
  return {...initialState}

@felipemartim
Copy link
Author

felipemartim commented May 6, 2016

Thanks for the quick reply!

I believe that short term workaround wouldn't work for me, due to the fact that my initial state is an Immutable Record. But I'll give it a try later. For now, I'm just returning the initial state with a "hasSignedOut" flag set to true, so it will be different than the initial state.

And I also believe setting lastState to the restoredState would solve the issue. 👍

@gullitmiranda
Copy link

gullitmiranda commented Jun 5, 2016

the comparison of objects in javascript does not work very well. Thus the state[key] == reducedState[key] (in /src/autoRehydrate.js#L29) will always return false if the content is an object.

e.g.:

$ node --version
v6.0.0

$ node
> a = {"_status":null,"data":null,"entities":{},"model":{},"errors":null,"error":null}
{ _status: null,
  data: null,
  entities: {},
  model: {},
  errors: null,
  error: null }
> b = {"_status":null,"data":null,"entities":{},"model":{},"errors":null,"error":null}
{ _status: null,
  data: null,
  entities: {},
  model: {},
  errors: null,
  error: null }
> a == b
false
> a !== b
true

@felipemartim
Copy link
Author

@gullitmiranda, as I'm using Immutable.js Records, this equality check returns true. However, after upgrading to 3.1.0, the issue got solved for me, so I'm closing this.

Thanks @rt2zz !

@rt2zz
Copy link
Owner

rt2zz commented Jun 7, 2016

@felipemartim I forgot to update here, we now set initialState to an empty object, so state will always persist after the first load, thus solving your issue and also enabling https://github.com/wildlifela/redux-persist-migrate

@gullitmiranda that is true, but in idiomatic redux if you do not modify state you return the object as is with referential equality. e.g.

let a ={}
let b = {}
a === b // false
a === a // true

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants