rt2zz / redux-persist

persist and rehydrate a redux store
MIT License
12.95k stars 866 forks source link

reducer is initialized by default parameters before sync with local storage #111

Closed captainkovalsky closed 1 year ago

captainkovalsky commented 8 years ago

Hi guys, when I configure stores app is rendered with initialState after that data will be sync and re-rendered with data from localStorage. Can I initialize store immediately with localStorate instead?


const configureStore = function configureStore(initialState) {
  const store = createStore(reducer, initialState, compose(
    autoRehydrate(),
    applyMiddleware(thunk),
    window.devToolsExtension ? window.devToolsExtension() : f => f
  ));

  if (module.hot) {
    // Enable Webpack hot module replacement for reducers
    module.hot.accept('../reducers', () => {
      const nextReducer = require('../reducers');
      store.replaceReducer(nextReducer);
    });
  }

  return store;
};

const store = configureStore({applications, candidates, settings, vacancies});
persistStore(store);
madc commented 8 years ago

I'm having a similar setup and the same issue.

Store Setup

const router = routerMiddleware(hashHistory);
const sagaMiddleware = createSagaMiddleware();

const enhancer = compose(
    autoRehydrate(),
    applyMiddleware(sagaMiddleware, router, logger),
    devTools(),
    persistState(
        window.location.href.match(
            /[?&]debug_session=([^&]+)\b/
        )
    )
);

export default function configureStore(initialState) {
    const store = createStore(rootReducer, initialState, enhancer);
    persistStore(store, {
        whitelist: ['settings']
    });
    sagaMiddleware.run(rootSaga);
    if (module.hot) {
        module.hot.accept('../reducers', () =>
            store.replaceReducer(require('../reducers'))
        );
    }
    return store;
}

Reducer

const initialState = {
    recentProjectsPath: ''
};

export default function settings(state = initialState, action) {
    switch (action.type) {
    case SET_PROJECT_DIR_PATH:
        return { ...state, recentProjectsPath: action.payload.path };
    default:
        return state;
    }
}

The information is persisted correctly, but when the persist/REHYDRATE action fires (after @@router/LOCATION_CHANGE), the next state is set with the initialState value. The payload itself contains the persist data.

Btw, I noticed, that persist/REHYDRATE fires, even if I don't call autoRehydrate. Does that make sense?

If I listen to REHYDRATE in my reducer, the payload has already been set to the initialState..

RajnishDashora commented 8 years ago

about persist/REHYDRATE getting fired even when you don't call autoRehydrate : as far as I understand it happens internally with persistStore(); function call.

madc commented 8 years ago

That would mean, that autoRehydrate, implemented like above, would not fire. Any ideas on how to call it with compose?

RajnishDashora commented 8 years ago

AFAIK, autoRehydrate is just another enhancer to the store which helps you by saving some Extra lines of code to handle REHYDRATE action per reducer . need to explore more about the compose.

rt2zz commented 8 years ago

Ya that is correct, autoRehydrate simply handles the REHYDRATE action. all of the heavy lifting is done in persistStore.

I think the original question is about how to syncronously load state before rendering the app. This is not possible, I would recommend either showing a temporary loading screen, or completely delaying the rendering of the react tree until persistence is complete.

If you need more control over when and how things fire you can use getStoredState and createPersistor.

madc commented 8 years ago

I will dig into it and report back on any new findings.

madc commented 8 years ago

My issue is solved. It was partly the delayed loading of the re-hydrated state and partly some issue with my code that worked well together. I feel like I hijacked this issue, sorry about that and thanks for your help.

rt2zz commented 8 years ago

👍

gausie commented 8 years ago

@vdzundza it looks like you're using the react-boilerplate. I'm using the same boilerplate and similarly struggling with getting redux-persist to work properly.

fforres commented 8 years ago

@vdzundza @gausie Did you guys manage to implement it? I'm a little bit lost on how the asyncronous injection of reducers handles the stores

Kinjeiro commented 7 years ago

For example, there is recipe "Delay Render Until Rehydration Complete" https://github.com/rt2zz/redux-persist/blob/master/docs/recipes.md#delay-render-until-rehydration-complete

funwithtriangles commented 7 years ago

For anyone struggling with this, just call persistStore again after injecting the new reducers.

stevemao commented 6 years ago

Is this still a issue in v5? https://github.com/rt2zz/redux-persist/issues/490 looks like a good solution.