rt2zz / redux-persist

persist and rehydrate a redux store
MIT License
12.96k stars 865 forks source link

autoRehydrate() not queueing actions as expected #403

Open nikita-malyschkin opened 7 years ago

nikita-malyschkin commented 7 years ago

I have an issue, that autoRehydrate is not queueing actions as described in the documentation.

autoRehydrate(config) This is a store enhancer that will automatically shallow merge the persisted state for each key. Additionally it queues any actions that are dispatched before rehydration is complete, and fires them after rehydration is finished.

this ist what redux devtools shows me: rehydrate_bug

this is how i create my store:

const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const store = createStore(
    combineReducers(Object.assign({ routing: routerReducer }, reducers)),
    composeEnhancers(autoRehydrate(), applyMiddleware(workerConnection.middleware))
);

I tried changing the order of the enhancers, but it did not change anything. I even tried without the devtools, but the same unwanted side-effects accrued as actions being dispatched before rehydration.

ms88privat commented 7 years ago

Same problem here. This solves the problem:

const renderAppAfterRehydrate = () => {
    persistStore(store, { whitelist: [ 'auth' ] }, () => {
        const history = syncHistoryWithStore(browserHistory, store);
        ...
tianguanghui commented 7 years ago

@ms88privat @nikita-malyschkin Hi,I have the same problem.This is how I create my store:

import { createStore, compose, combineReducers, applyMiddleware } from 'redux';

import createHistory from 'history/createBrowserHistory';
import { routerReducer, routerMiddleware, push, LOCATION_CHANGE } from 'react-router-redux';

import { composeWithDevTools } from 'redux-devtools-extension';
import thunkMiddleware from 'redux-thunk';
import logger from 'redux-logger';
import axiosMiddleware from 'redux-axios-middleware';

import { persistStore, autoRehydrate } from 'redux-persist';
import { REHYDRATE } from 'redux-persist/lib/constants';
import createActionBuffer from 'redux-action-buffer'

import httpClient from '../utils/HttpUtils';
import rootReducer from '../reducers/index';
import initialState from '../models/index';

let reducer = combineReducers({
    ...rootReducer,
    router: routerReducer
});

let history = createHistory();

let debugware = [];
if (process.env.NODE_ENV !== 'production') {
    debugware.push(logger);
}

let enhancer = composeWithDevTools(
    autoRehydrate({log: false}),
    applyMiddleware(
        thunkMiddleware,
        createActionBuffer(REHYDRATE),
        axiosMiddleware(httpClient),
        routerMiddleware(history),
        ...debugware
    )
);

const store = createStore(reducer, initialState, enhancer);

persistStore(store, {}, () => {
    console.log('persistStore complete');
});

export { history, store, push };

i have use the 'redux-action-buffer' Middleware, and place 'createActionBuffer(REHYDRATE)' behind the 'thunkMiddleware' and before all the others. then i get the right store that recovery from the localStage when the app init.

orenfromberg commented 7 years ago

I also took advantage of the optional callback parameter on persistStore() as @ms88privat did above. I used it to dispatch an action that lets the app know that we are ready to render since at that point the state has been rehydrated.

const setIsReady = () => ({
    type: SET_IS_READY,
    payload: true
})

persistStore(store, { blacklist: ['isReady']}, () => {
    store.dispatch(setIsReady());
});

Note that I've added isReady to the blacklist.

Here is the reducer:

export default (state = false, action) => {
    switch(action.type) {
        case SET_IS_READY:
            return action.payload;
        default:
            return state;
    }
}

Finally, in my App root component I have this render logic:

  render() {
    if (!this.props.isReady)
      return <div />;

    // render the app as normal
    return (
      <div>...
sparameshwar commented 6 years ago

Any resolution on this issue? I have the same problem. Actions I dispatch before the store is rehydrated are executed immediately instead of being queued up behind the rehydration.