react-router-redux 和 redux-immutable:你不能改变 <Router history>;它将被忽略

react-router-redux and redux-immutable: You cannot change <Router history>; it will be ignored

我正在尝试将 react-router-redux 与 redux-immutable 一起使用,但在触发 @@router/LOCATION_CHANGE 操作时出现错误:

action @ 14:19:07.625 @@router/LOCATION_CHANGE 
%c prev state color: #9E9E9E; font-weight: bold Map { "repos": Map { "loading": false, "reposCount": 0 }, "users": Map { "loading": false, "usersCount": 0 }, "router": Map { "locationBeforeTransitions": null } }
%c action color: #03A9F4; font-weight: bold { type: '@@router/LOCATION_CHANGE',
  payload: 
   { pathname: 'blank',
     search: '',
     hash: '',
     state: null,
     action: 'POP',
     key: '5b05pd',
     query: {},
     '$searchBase': { search: '', searchBase: '' } } }
%c next state color: #4CAF50; font-weight: bold Map { "repos": Map { "loading": false, "reposCount": 0 }, "users": Map { "loading": false, "usersCount": 0 }, "router": Map { "locationBeforeTransitions": Map { "pathname": "blank", "search": "", "hash": "", "state": null, "action": "POP", "key": "5b05pd", "query": Map {}, "$searchBase": Map { "search": "", "searchBase": "" } } } }
—— log end ——
<Provider> does not support changing `store` on the fly. It is most likely that you see this error because you updated to Redux 2.x and React Redux 2.x which no longer hot reload reducers automatically. See https://github.com/reactjs/react-redux/releases/tag/v2.0.0 for the migration instructions.
Warning: [react-router] You cannot change <Router history>; it will be ignored

我在网上看到这个问题似乎是由热加载程序引起的,但我没有使用它。

代码如下所示:

路线

const routes = (
    <Route path="/" component={AppLayout}>
        <IndexRoute component={Home} />
        <Route path="/users" component={UsersPage} />
        <Route path="/repos" component={ReposPage} />
    </Route>
);

根组件

class Root extends React.Component<RootComponentProps, void> {
  public render() {
    const { store, history, routes } = this.props;
    return (
      <Provider store={store}>
        <div>
          <Router history={history}>
            {routes}
          </Router>
          <DevTools />
        </div>
      </Provider>
    );
  }
}

routerReducer

const initialRouterReducerState = Immutable.fromJS({
    locationBeforeTransitions: null
});

let routerReducer = (state = initialRouterReducerState, action: any) => {
    if (action.type === LOCATION_CHANGE) {
        return state.merge({
            locationBeforeTransitions: action.payload
        });
    }
    return state;
};

主要

// ...

let history = syncHistoryWithStore(browserHistory, store, {
    selectLocationState: (state: any) => state.get("routing").toJS()
});

render(
    <Root store={store} history={history} routes={routes} />,
    document.getElementById(container)
);

您对导致此问题的原因有任何想法吗?

让我们在这里阅读错误:

<Provider> does not support changing store on the fly. It is most likely that you see this error because you updated to Redux 2.x and React Redux 2.x which no longer hot reload reducers automatically. See https://github.com/reactjs/react-redux/releases/tag/v2.0.0 for the migration instructions.

在您的根组件中,您从 props 获取 store,并且在每次路由更改时,它都会重新渲染所有内容。

https://github.com/reactjs/react-redux/blob/master/docs/api.md#react-router-10

Provider 应该呈现为顶级组件。路线会适当改变并传递道具,供应商会通过单一商店传递一切。

ReactDOM.render(
  <Provider store={store}>
    <Router history={history}>...</Router>
  </Provider>,
  targetEl
)

供应商应该与您的商店一起位于顶部。你应该有许多不同的减速器。

原来我的问题都是jsdom配置错误导致的。我创建了一个 dom.ts 文件,我可以从包含 mocha 单元测试的文件中导入该文件:

/// <reference path="../src/interfaces/interfaces.d.ts" />

let jsdom = require("jsdom");

// setup the simplest document possible
let doc = jsdom.jsdom(
    `<!doctype html>
    <html>
        <body>
            <div id="root"/><div>
        </body>
    </html>`,
    {
        url: "http://redux-bootstrap.com/"
    }
);

// get the window object out of the document
let win = doc.defaultView;

// set globals for mocha that make access to document and window feel 
// natural in the test environment
let g: any = global;
g.document = doc;
g.window = win;

// take all properties of the window object and also attach it to the 
// mocha global object
propagateToGlobal(win);

// from mocha-jsdom https://github.com/rstacruz/mocha-jsdom/blob/master/index.js#L80
function propagateToGlobal (window: any) {
  for (let key in window) {
    if (!window.hasOwnProperty(key)) { continue; }
    if (key in global) { continue; }
    g[key] = window[key];
  }
}