web-dev-qa-db-ja.com

Redux-ホットリロード中にレデューサーの状態を維持する方法

React + Redux + Webpack + WebpackDevserverを使用します。ホットローダーが起動すると、すべてのレデューサーが初期状態にリセットされます。

どういうわけかレデューサーを実際の状態に保つことはできますか?

私のWebpack構成には次のものが含まれています。

entry: [
    "./index.jsx"
],
output: {
    filename: "./bundle.js"
},
module: {
    loaders: [
        {
            test: /\.js|\.jsx$/,
            exclude: /node_modules/,
            loaders: ["react-hot","babel-loader"],
         }
    ]
},
plugins: [
    new webpack.HotModuleReplacementPlugin()
]

私のレデューサーの統計:

const initialState = {
...
}

export default function config(state = initialState, action) { ...

WebpackDev-Serverを次の方法で起動します。

"start": "webpack-dev-server",
15
Tomas Randus

Babel 6を想定すると、これに沿って何かを行う必要があります。

import {createStore} from 'redux';
import rootReducer from '../reducers';

export default function configureStore(initialState) {
  const store = createStore(rootReducer, initialState);

  if(module.hot) {
    // Enable Webpack hot module replacement for reducers
    module.hot.accept('../reducers', () => {
      const nextReducer = require('../reducers/index').default;

      store.replaceReducer(nextReducer);
    });
  }

  return store;
}

私の reduxデモ で実際のアプローチを見ることができます。

17

ストアの作成に関連するコードを確認してください-createStore()。ストアはapp.jsの外部に構築する必要があります。そうしないと、HMRが更新されるたびにotがフラッシュされます。

違う:

// app.js

import React from 'react';
import ReactDOM from 'react-dom';
import { hot } from 'react-hot-loader';
import { Provider } from 'react-redux';
import { PersistGate } from 'redux-persist/lib/integration/react';
import { AppWidget } from 'containers';
import createStore from 'store/create-store';

const { store, persistor } = createStore(); // <!--- NEW STORE ON HMR, BUG

const rootElement = window.document.getElementById('appWidget');

const render = (Component) => {
  ReactDOM.render(
    <Provider store={store}>
      <PersistGate loading={null} persistor={persistor}>
        <Component />
      </PersistGate>
    </Provider>,
    rootElement,
  );
};

render(process.env.NODE_ENV === 'development' ? hot(module)(AppWidget) : AppWidget);

正しい:

// app.js

import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { AppWidget } from 'containers';
import store from 'store/create-store';
import { AppContainer } from 'react-hot-loader';

const rootElement = window.document.getElementById('appWidget');

const render = (Component) => {
  ReactDOM.render(
    <AppContainer>
      <Provider store={store}>
        <Component />
      </Provider>
    </AppContainer>,
    rootElement,
  );
};

render(AppWidget);

if (module.hot) {
  module.hot.accept();
}

// create-store.js

import { applyMiddleware, compose, createStore } from 'redux';
import createSagaMiddleware from 'redux-saga';
import thunk from 'redux-thunk';
import rootReducer from './reducers';
import rootSaga from './sagas';

const doCreateStore = () => {
  const sagaMiddleware = createSagaMiddleware();
  const middleware = [
    thunk,
    sagaMiddleware,
  ];

  const store = createStore(
    rootReducer,
    compose(
      applyMiddleware(...middleware),
    ),
  );

  sagaMiddleware.run(rootSaga);

  return store;
};

export default doCreateStore(); // <!-- CREATE AND RETURN STORE, NO BUG

1