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

Manual rehydrate #952

Closed
bohdan145 opened this issue Dec 20, 2018 · 21 comments · Fixed by #986
Closed

Manual rehydrate #952

bohdan145 opened this issue Dec 20, 2018 · 21 comments · Fixed by #986
Labels

Comments

@bohdan145
Copy link

How can i stop automatic re-hydration and launch it manually only if there is no internet connection ?

@aguynamedben
Copy link
Collaborator

I'm not sure how to to do that, but I'm curious about your use case... why do you want to stall rehydration until there is internet? Are you using a custom storage that requires internet? My app just uses localStorage, so I don't care if there is internet during rehydration.

Also, note the v4->v5 updates for autoRehydrate: https://github.com/rt2zz/redux-persist/blob/208c6b112ead87b3701dfacaae2cdbe78377775a/docs/MigrationGuide-v5.md#migration-from-v4-to-v5 Maybe something in there will help you figure out what to do here.

@bohdan145
Copy link
Author

Because in my application(chatting app) i store messages locally, but what if messages was changed when i was offline ? (like deleted or changed text). How do i know that i need to delete my local message or change it to be the same as server version?

@cvanem
Copy link

cvanem commented Jan 2, 2019

@bohdan145 It might not be the best way, but I believe you can just intercept the 'persist/REHYDRATE' action for your desired store(s). In your store's reducer you can either return the hydrated payload or your original state. Inside your desired reducer you would add something like this:

case 'persist/REHYDRATE':
  const payload = (action as any).payload;
  const shouldHydrate = false; //or true
  const newState = shouldHydrate ? payload.myStore : state;      
  return {
    ...newState,
  };

That would at least allow you to prevent hydration based on your internet connection. I'm sure there is a way to re-trigger the hydration logic once the internet is restored although I am not sure how. Maybe you can dispatch the REHYDRATE action or re-initialize the persistor to accomplish this.

@leoek
Copy link
Contributor

leoek commented Jan 27, 2019

Hi I am interested in this as well. I need to stall the rehydration until my storage is initialized, which can only be done after the user entered a password which will be used for file level decryption in the implementation of the storage.

@leoek
Copy link
Contributor

leoek commented Jan 30, 2019

@aguynamedben Do you have any ideas whether this is possible or not, or who might now?

@cvanem
Copy link

cvanem commented Jan 30, 2019

@leoek I think you can accomplish what you need by ignoring the initial hydration and then manually re-hydrating using getStoredState.

Once you have the state you can dispatch the necessary actions to update your app state as needed. If you use my example above you could dispatch 'persist/REHYDRATE' with shouldHydrate set to true and include the data from getStoredState in the dispatched action.

If that doesn't work for whatever reason, another idea would be to delay the persistor initialization and adding the persistedReducer to your store until your storage is initialized. That seems like it should work in theory, but might get messy.

@leoek
Copy link
Contributor

leoek commented Feb 2, 2019

@cvanem Thank you for the suggestion. This seems like a viable option. In theory I only need to encrypt parts of the state i am persisting and I should be able to use multiple persistors. One configured like this:

const persistConfig = {
  key: "root",
  storage: FSStorage(),
  whitelist: ["some", "key"],
  transforms: []
};

and one for each encrypted reducer which is initialized later, configured like this:

const encryptedPersistConfig = {
  key: "encryptPart",
  storage: FSStorage(<credentials which are not available at startup>),
  transforms: []
};

Are there any cave hats with the usage of multiple persistors, you know of?

@mauriciopasquier
Copy link

To me it seems "obvious" that a manual rehydration would reset the store just the same as restarting the app, white/blacklisting taken into account. Wouldn't it be a common use cast, "just discard all the state not whitelisted", for example?

@leoek
Copy link
Contributor

leoek commented May 10, 2019

@mauriciopasquier rehydration does not reset the state. I believe the default reducer for rehydration does a shallow merge. If you need to merge within a deeper level you can use your own reducer.

(Manual means delayed until a manual callback is triggered. You can check the implementation in #986 This is only a very little change. We are using it in production for quite a while now, without any issues.)

@mauriciopasquier
Copy link

@leoek thanks for your reply, I guess I'll implement "restarting" manually then, but I wanted to KISS and DRY with redux-persist white/blacklisting configuration.

@leoek
Copy link
Contributor

leoek commented May 16, 2019

@mauriciopasquier Your requirement seems unrelated to this issue. I think it is best if you open a new issue and pull request for that.

@rt2zz rt2zz closed this as completed in #986 Jul 5, 2019
@bitflower
Copy link

@cvanem Can you elaborate a bit on what getStoredState is?

@leoek
Copy link
Contributor

leoek commented Aug 7, 2020

@bitflower getStoredState is the function which retrieves the state (through the provided storage), deserializes it and than applies the provided transformations. I believe you can get a pretty good understanding from the source: https://github.com/rt2zz/redux-persist/blob/master/src/getStoredState.js

@bitflower
Copy link

bitflower commented Aug 7, 2020

Thanks @leoek I swear I had previously tried to import it but didn't find it. Got it now ;-)

@cvanem says "I think you can accomplish what you need by ignoring the initial hydration and then manually re-hydrating using getStoredState." - I wonder how this can be achieved on a global level. Not on a per-reducer basis as also described in this thread.

@leoek
Copy link
Contributor

leoek commented Aug 7, 2020

This was about doing the rehydration manually at a custom point in time (instead of doing it right after the application startup). However to achieve this you don't need to use getStoredState manually, as it was integrated into redux-persist with #986

@bitflower
Copy link

@leoek I've played around with manualPersist earlier and it seemed to rehydrate right one the beginning. Does this option effect only persisting or also rehydration?

@bitflower
Copy link

btw I've decided to add the reducer and persistor only after the user is logged in. I need seperate storages per user. This way I hope to be able to customize the storage after login and then "add" the persistor.

@leoek
Copy link
Contributor

leoek commented Aug 7, 2020

Setting manualPersist to true delays the rehydration (and persistence) until persistor.persist() is called.

This way I hope to be able to customize the storage after login and then "add" the persistor.

This is exactly what it was intended for.

@bitflower
Copy link

Aha, so procedure would look something like:

1: Setup store incl. persistence, manualPersist: true
2: User logs in
3: Configure persistence storage according to requirements for example incl. user info
4: Call persistor.persist() to "read" the persisted state the first time and continuously persist from then on

I wonder how to achieve 3: when the persist config was already defined in 1:

Thanks again for some more breadcrumbs ;-)

@bitflower
Copy link

Nvmd, found it out. I can set the config again in persistReducer to make it user agnostic.

I might PR a fix for the persistStore type which doesn't recognize the manualPersist option for me. I needed to cast to make it work:

persistor = persistStore(
    store,
    ({
      manualPersist: true
    } as unknown) as PersistorOptions
  );

Do you use typescript @leoek ?

Thanks again for your input and have a nice Sunday :-)

@albanx
Copy link

albanx commented Apr 23, 2023

I have a similar issue. I need to hydrate the store only once the user has logged in, so that I can create a persistent store only by using the user id in react native (in case the user uses different account to login in the app)

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

Successfully merging a pull request may close this issue.

7 participants