Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 336
amirfl Avatar asked Aug 03 '16 14:08

amirfl


People also ask

What is initial state in react redux?

The state that we use inside redux as a store can only be modified with the help of the actions. But, this state must be specified somewhere first to use it. We prefer to declare our initial state at the reducer files. Then we use that reducer in the store and provide that store use inside the whole application.

Where does redux store data persist?

With the Redux Persist library, developers can save the Redux store in persistent storage, for example, the local storage. Therefore, even after refreshing the browser, the site state will still be preserved.

How do I set redux state to initial state?

You can set it at the reducers . Reducers can also set initialState by looking at the incoming state argument (which would be undefined if createStore is not called with initialState ) and returning the values they would like to use as default.


1 Answers

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.

like image 147
amirfl Avatar answered Sep 17 '22 08:09

amirfl