0

我正在使用使用 Redux 的 React Boilerplate。我已下载 Redux Chrome 开发工具,但一直收到此错误

combineReducers.js:29 The previous state received by the reducer is of unexpected type. Expected argument to be an instance of Immutable.Iterable with the following properties: "route", "language", "global".

我一直在调试这个东西,但无济于事。我所看到的是combineReducers返回一个函数,它的第一行是

var inputState = arguments.length <= 0 || arguments[0] === undefined ? _immutable2.default.Map() : arguments[0];

我注意到这里的断点命中了两次。第一次,论点正是它们应该是的

在此处输入图像描述

但是第二次我的论点看起来像这样

在此处输入图像描述

出于某种原因,arguments[0]从 Map 类型更改为文字对象。所以两个问题:

  • 为什么 Redux 在 INIT 上多次运行 combineReducers?
  • 为什么初始化时我的参数会改变?

这是 React Boilerplate 中 store.js 的代码。我只添加了对persistStore 的导入和调用。

import { createStore, applyMiddleware, compose } from 'redux';
import { fromJS } from 'immutable';
import { routerMiddleware } from 'react-router-redux';
import createSagaMiddleware from 'redux-saga';
import createReducer from './reducers';
import { persistStore, autoRehydrate } from 'redux-persist';

const sagaMiddleware = createSagaMiddleware();

export default function configureStore(initialState = {}, history) {
    // Create the store with two middlewares
    // 1. sagaMiddleware: Makes redux-sagas work
    // 2. routerMiddleware: Syncs the location/URL path to the state
    const middlewares = [
        sagaMiddleware,
        routerMiddleware(history),
    ];

    const enhancers = [
         applyMiddleware(...middlewares),
    ];

    // If Redux DevTools Extension is installed use it, otherwise use Redux compose
    /* eslint-disable no-underscore-dangle */
    const composeEnhancers =
        process.env.NODE_ENV !== 'production' &&
        typeof window === 'object' &&
        window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ ?
            window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ : compose;
    /* eslint-enable */

    //get the state from localStorage
    // const persistedState = loadState();
    const store = createStore(
        createReducer(),
        fromJS(initialState),
        composeEnhancers(...enhancers)
    );

    // Extensions
    store.runSaga = sagaMiddleware.run;
    store.asyncReducers = {}; // Async reducer registry

    // Make reducers hot reloadable, see http://mxs.is/googmo
    /* istanbul ignore next */
    if (module.hot) {
        module.hot.accept('./reducers', () => {
            import('./reducers').then((reducerModule) => {
                const createReducers = reducerModule.default;
                const nextReducers = createReducers(store.asyncReducers);

                store.replaceReducer(nextReducers);
            });
        });
    }

    persistStore(store);

    return store;
}

编辑

这是主要的reducer文件。它引入了其他减速器文件。

/**
 * Combine all reducers in this file and export the combined reducers.
 * If we were to do this in store.js, reducers wouldn't be hot reloadable.
 */

import { combineReducers } from 'redux-immutable';
import { fromJS } from 'immutable';
import { LOCATION_CHANGE } from 'react-router-redux';

import languageProviderReducer from 'containers/LanguageProvider/reducer';
import globalReducer from 'containers/App/reducer';

/*
 * routeReducer
 *
 * The reducer merges route location changes into our immutable state.
 * The change is necessitated by moving to react-router-redux@4
 *
 */

// Initial routing state
const routeInitialState = fromJS({
    locationBeforeTransitions: null,
});

/**
 * Merge route into the global application state
 */
function routeReducer(state = routeInitialState, action) {
    switch (action.type) {
      /* istanbul ignore next */
      case LOCATION_CHANGE:
          return state.merge({
              locationBeforeTransitions: action.payload,
      });
      default:
        return state;
    }
}

/**
 * Creates the main reducer with the asynchronously loaded ones
 */
export default function createReducer(asyncReducers) {
    return combineReducers({
        route: routeReducer,
        language: languageProviderReducer,
        global: globalReducer,
        ...asyncReducers,
    });
}
4

0 回答 0