Hydration doesn't always hydrate properly.
losh11 opened this issue · 5 comments
Hi, been using this package alongside redux-persist for a while now... Was working great until recently...
In the last couple of days I've noticed that during hydration all of the data is missing. This occurs infrequently. Usually have to force quit the app over a couple of minutes to reproduce. Not really sure what's causing it - switched to Asyncstorage and everything working fine - so I think it might be something to do with react-persist-sensitive-storage
.
Package:
react-native-sensitive-info
: 5.5.1
redux-persist
: 6.0.0
"redux": "^4.0.4"
Here's what my store looks like:
import {createStore, applyMiddleware, compose} from 'redux';
import {persistStore, persistReducer} from 'redux-persist';
import createSensitiveStorage from 'redux-persist-sensitive-storage';
import thunk from 'redux-thunk';
import reducer from './src/reducers';
const initialState = {};
const middleware = [thunk];
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const storage = createSensitiveStorage({
keychainService: 'appNameKeychain',
sharedPreferencesName: 'appNameKeystore',
});
const persistConfig = {
key: 'root',
storage,
};
const pReducer = persistReducer(persistConfig, reducer);
export const store = createStore(
pReducer,
initialState,
composeEnhancers(applyMiddleware(...middleware)),
);
export const pStore = persistStore(store);
and my App.js (entry point):
...
const App: () => React$Node = () => {
return (
<>
<Provider store={store}>
<PersistGate loading={null} persistor={pStore}>
<Navigation />
</PersistGate>
</Provider>
</>
);
};
and my root reducer looks something like this:
import {combineReducers} from 'redux';
import xreducer from './xreducer';
import xreducer1 from './xreducer1';
export default combineReducers({
xreducer,
xreducer1
});
Any help with diagnosing this issue would be welcome.
Hey @losh11, could you create a repro for this issue? I've been having trouble reproducing it. Also, not sure if this is related, but redux-persist 6.0.0 is a fairly recent release. Did you notice it before upgrading that package?
Our team just ran into this exact same issue, so I used Reactotron to diagnose what is going on. Turns out that a few seconds after sending the app to the background, the following error is thrown:
Then when bringing the app to the foreground, Reactotron shows an empty payload for the persist/REHYDRATE
action, indicating that the state wasn't persisted correctly.
I can also confirm that switching to @react-native-community/async-storage
fixes the issue.
@richeterre Thanks for the excellent detective work! From this error message, it looks as though react-native-sensitive-info is not being allowed to write to the secure storage after the application has been sent to the background.
It's been a couple of years since I spent any significant time in this codebase, but if I'm remembering correctly, redux-persist will attempt to persist the Redux store whenever the store updates.
I'm wondering if your application dispatches an action as it goes into the background, which triggers redux-persist to attempt to persist the store, but that is now failing because the OS isn't allowing the secure storage to be written by a background application? This is all just speculation on my part.
From what I can see, I don't think there's anything we can do in this library to address the issue, as we're not the ones doing the actual write to the secure storage area. That part is handled by react-native-sensitive-info, so perhaps you could report this issue to that project to see if they've got any insight that might help.
If you disagree and think there is something we can do here, please re-open and let us know what that might be.
@losh11 @richeterre One more thing: it would probably be worth mentioning whether this issue happens on iOS, Android, or both (and which versions of the OS) when you open the issue on react-native-sensitive-info. Perhaps this is new behavior with iOS 13?
Thanks @randycoulman for your detailed response! I had already suspected the same – that the issue is with react-native-sensitive-info
. I've worked around the bug for now by switching to the react-native-keychain
library and a lightweight wrapper around it.
I'm wondering if your application dispatches an action as it goes into the background, which triggers redux-persist to attempt to persist the store, but that is now failing because the OS isn't allowing the secure storage to be written by a background application?
Yes, our app does regular polling on its home screen, which continues for some time in the background until the OS shuts it down. Part of this state is included in the persisted whitelist. So that's likely the reason why the persisted store gets "corrupted" as the write eventually fails.
For me this happens on iOS (not supporting Android right now, so can't say) and it did start around the time we upgraded to iOS 13. On the other hand, we did some big React Native upgrades around the same time, so I can't say for sure what caused it.