redux-persist
redux-persist copied to clipboard
Unable to use persist() after initial hydration
Whenever I try to use persistor.persist() after the store has completed initial hydration the following is dispatched for each persisted reducer:
{ type: 'persist/REHYDRATE', err: {}, key: 'some_random_key', some_key: "somevalue" }
I'm adding 'some_key' to every dispatch working with the BroadcastChannel API (not sure if that matters). I've been able to replicate this in many situations, ...with or without manual persist, after flushing, etc.
Also, it seems that no matter what it waits till the default timeout is reached before dispatching these for all persisted reducers.
@rt2zz Hoping you can take a look at this and see if it makes sense, thanks!!
Hey @rowrowrowrow , I'm confused what you mean here -- I think the rehydrate dispatch is expected on persist(), for the pause() -> persist() usecase?
I'm using this behavior to intentionally trigger extra rehydrates, so I want to make sure I'm understanding how the rehydrate works properly. Cheers!
Hi @JacobJaffe , does this break the pause() -> persist() usecase for you?
I think to answer your question, for me and without the proposed change, the rehydrate dispatch is made regardless but can throw an error if persist already exists in a reducer's state because that's all it checks for. So it just times out instead of gathering the stored data. Is this not what you're experiencing?
The proposed change provides the user a lot more flexibility in how they manage rehydration and I think makes a lot more sense as to the purpose of having the rehydrated property in state, let me know if it works for you as I'm moving forward with it either way.
I just tried it out, for me this doesn't resolve the use case. Once it returns in that example it doesn't attempt to get data to rehydrate and after setting _sealed to true it just prevents the rehydrate dispatch (with an error after timing out) from dispatching which I'm not sure is good thing.
Oops, didn't mean to delete my previous comment. For context, it was a suggestion to change
if (_persist) {
_sealed = true; // <-- ADDED
return {
...baseReducer(restState, action),
_persist,
};
}
~~
Anyways-- yeah, that's a suggestion for helping the noop contract of what occurs on multiple persists. The way I see it is that if persist() has a noop contract on multiple uses, then it shouldn't always dispatch the error (say, if something else is waiting on intercepting rehydrate actions, then it's not really a noop). Alternatively, if it is critical to always dispatch some kind of rehydrate action, it could immediately dispatch a more explicit action indicating that the rehydrate will not occur, instead of waiting for the timeout to resolve and then failing generically.
I agree that what you're describing would need the && !_persist.rehydrated changes -- I'm unsure if that would break anything else though, as that does change the contract of persist().
Ya, for me the proposed changes seem necessary and it works great/as expected now, but then again it might break for cases other than mine. I just haven't experienced any breaks and would not like to fork if I don't have too.
Would something like the following make sense? Thanks for the input and help too!
if (_persist && !_persist.rehydrated) {
_sealed = true; // <-- ADDED
return {
...baseReducer(restState, action),
_persist,
};
}
@JacobJaffe I just pushed the changes with your recommendations. It's working great for me can you let me know if you find any issues or if we need to approach this problem in a different way to contribute back to the package. Best!
and work for me too. Thanks!! v6.0.0 RN 60.2
Hi, How is this supposed to work?
I just want to stop the persist before an action and resume 500ms after but:
persistor.pause();
persistor.persist()
It throws a timeout error and resumes the store to persist future actions but does not persist the current state.
How can i force the persist to save the current state?