react-router-redux и redux-immutable: вы не можете изменить «Историю маршрутизатора»; это будет проигнорировано

Я пытаюсь использовать 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>
    );
  }
}

маршрутизаторРедуктор

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)
);

Есть ли у вас какие-либо идеи о том, что может быть причиной этой проблемы?


person Remo H. Jansen    schedule 17.04.2016    source источник


Ответы (2)


Давайте прочитаем ошибку здесь:

‹Поставщик› не поддерживает изменение store на лету. Скорее всего, вы видите эту ошибку, потому что вы обновились до Redux 2.x и React Redux 2.x, которые больше не выполняют автоматические редукторы горячей перезагрузки. См. https://github.com/reactjs/react-redux/releases/tag/v2.0.0 для получения инструкций по миграции.

В вашем корневом компоненте вы берете store из реквизита и при каждом изменении маршрута он перерисовывает все.

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

Провайдер должен отображаться как компонент верхнего уровня. Маршруты менялись бы правильно и передавали реквизиты, а провайдер пропускал бы все через единый магазин.

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

Провайдер должен быть наверху, с вашим магазином. и у вас должно быть много разных редукторов.

person Blair Anderson    schedule 17.04.2016
comment
Является ли для реактивного маршрутизатора 0.13? Я использую ^ 2.2.4 - person Remo H. Jansen; 17.04.2016
comment
Это то, что я делаю, уже взгляните на мой код корневого компонента. - person Remo H. Jansen; 17.04.2016
comment
Я обновил код выше. Provider должен быть на самом верхнем уровне. Над ним ничего не должно быть. Корневой компонент не обязателен. - person Blair Anderson; 17.04.2016
comment
Извините, я только что попробовал, но проблема не в этом. - person Remo H. Jansen; 17.04.2016

Получается, что все мои проблемы были вызваны неправильной настройкой jsdom. Я создал файл dom.ts, который я могу импортировать из файлов, содержащих модульные тесты мокко:

/// <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];
  }
}
person Remo H. Jansen    schedule 18.04.2016