Search code examples
react-nativereduxasyncstorage

default values from initial state are loaded before store rehydrates with redux-persist


I'm having trouble accessing saved data after app starts with redux-persist.

The reducer initializes with data defined in my initial state. By the time the previous session's state loads with AsyncStorage, the component is already displayed with the default data.

I know that the data is saved and fetched successfully. If I leave the screen to a different one and come back to it, I can see that the data is displayed correctly. Debugging the state and props also shows that this is a async timing issue.

How can I delay the loading of the redux containers to after the store rehydrates. Alternatively, can I force update the conatainer (and its children) to update when the store finishes loading?

Here is what I've tried. to configure my store:

export default function configureStore(initialState) {
    const middlewares = [thunk];
    if (process.env.NODE_ENV === `development`) {
        const createLogger = require(`redux-logger`);
        const logger = createLogger();
        middlewares.push(logger);
    }

    let store = compose(
        applyMiddleware(...middlewares),
        autoRehydrate() )(createStore)(reducers);

        persistStore(store, {blacklist: ['routing'], storage: AsyncStorage}, () => {
            store.dispatch(storeRehydrateComplete())
        })


    return store
}

Hoping that this will update all other components (since all reducers in redux are called in an action), I've tried creating an action that triggers when the store finishes loading:

import { REHYDRATE_STORE } from './types'

export function storeRehydrateComplete(){
    return {
        type: REHYDRATE_STORE,
    }
}

And it's reducer: import { REHYDRATE_STORE } from '../actions/types' const initialState = { storeIsReady: false }

export default function reducer(state = initialState, action){
    switch (action.type) {
        case REHYDRATE_STORE:
            return {...state, storeIsReady:true}
            break;
        default:
            return state
            break;
    }
}

But although the storeIsReady state changes to true when rehydration is complete, I'm still couldn't figure out how to force update the container component.


Solution

  • I solved it by following this recipe: delay-render-until-rehydration-complete

    Basically the solution is as follows:
    In the component that wraps <Provider>, create a local state flag that tracks whether the store has rehydrated yet or not. Using the callback of persistStore() to update this flag. In the render function of this wrapper, if the flag is true, render <Provider>, otherwise, render some temporary view.