使用 Redux 反应热重载

Posted

技术标签:

【中文标题】使用 Redux 反应热重载【英文标题】:React Hot Reload with Redux 【发布时间】:2018-04-30 19:30:25 【问题描述】:

我已经使用 HMR / React Hot Reloader 完成了与视图相关的所有工作。但是在添加 redux、react-redux 等之后......每当我修改视图或减速器时,我都会收到以下错误:

<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.

点击错误中的链接会导致一篇关于明确使用 replaceReducer 的 2 年前的帖子,这就是我所做的。

我的版本:

"redux": "^3.7.2" "react-redux": "^5.0.6"

我有一种感觉,这主要是由于我不了解在哪里以及如何放置我的 module.hot.accept 调用(如果你可以有多个?)。相关代码如下。

boot.js(入口点)

import  Provider  from 'react-redux';
import  AppContainer  from 'react-hot-loader';
import  ConnectedRouter  from 'react-router-redux';

import App from './App';

import  configureStore, history  from './store/configureStore';

let store = configureStore();

function renderApp() 
    ReactDOM.render(
      <AppContainer>
        <Provider store=store>
          <ConnectedRouter history=history>
            <App />
          </ConnectedRouter>
        </Provider>
      </AppContainer>
      , document.getElementById("app"));


renderApp();

if (module.hot) 
    module.hot.accept(() => 
        renderApp();
    )

configureStore.js

import createHistory from 'history/createBrowserHistory';
import  createStore, combineReducers, compose, applyMiddleware  from 'redux';
import  routerMiddleware, routerReducer  from 'react-router-redux';
import thunk from 'redux-thunk';

import DevTools from '../components/DevTools';

import * as rootReducer from '../services/rootReducer';

const composeEnhancers = compose;

export const history = createHistory();

const middleware = routerMiddleware(history);

export function configureStore(initialState) 
  const reducers =  ...rootReducer, router: routerReducer ;

  const store =  createStore(
    combineReducers(reducers),
    initialState,
    composeEnhancers(
      applyMiddleware(middleware, thunk),
      DevTools.instrument()
    )
  );

  if (module.hot) 
    module.hot.accept('../services/rootReducer', () => 
      const nextRootReducer = require('../services/rootReducer').default;
      const finalReducer = ...nextRootReducer, router: routerReducer ;
      store.replaceReducer(finalReducer);
    )
  

  return store;

我的 configureStore 中的 module.hot.accept 从未真正调用过,因为 boot.js 中的父级是。能只有1个吗?!

如何摆脱这个错误?

或者,让我换个说法:我如何摆脱这个错误并正确设置带有 redux 存储的 react 热加载环境?

可能相关的 Github 问题:

https://github.com/reactjs/react-redux/issues/259

【问题讨论】:

【参考方案1】:

经过进一步研究,发现问题出在 boot.js 中的 accept 调用范围。由于它本质上是从根级应用程序观看所有内容,因此整个应用程序在减速器更改时重新加载,因此减速器的 HMR 接受从未被调用。以下是工作版本。

boot.js

if (module.hot) 
    module.hot.accept('./containers/App.js', () => 
        const nextApp = require('./containers/App').default;
        renderApp(nextApp);
    )

configureStore.js

  if (module.hot) 
    module.hot.accept('../services/rootReducer', () => 
      const nextRootReducer = require('../services/rootReducer');
      const finalReducer = ...nextRootReducer, router: routerReducer ;
      store.replaceReducer(combineReducers(finalReducer));
    )
  

【讨论】:

以上是关于使用 Redux 反应热重载的主要内容,如果未能解决你的问题,请参考以下文章

Cordova + 在开发模式下对热重载做出反应

启用单页应用响应热重载 webpack

如何在不使用电子锻造重定向到根目录的情况下进行热重装并做出反应

React slingshot - 使用反应路由器子路由时,Webpack 热中间件在 hot-update.json 上返回 404

使用热重载时简单的字符串标题不更新

使用 redux 反应原生导航 v3