Redux - 如何在热重载期间保持 reducer 状态
Redux - how to keep the reducer state during hot reload
我使用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()
]
我的 reducers 统计数据:
const initialState = {
...
}
export default function config(state = initialState, action) { ...
我通过以下方式启动我的 Webpack 开发服务器:
"start": "webpack-dev-server",
假设 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 demo.
上看到该方法的实际应用
检查与商店创建相关的代码 - 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
只需像下面那样在根元素中呈现应用程序的地方调整您的代码。
store.js:
export const store = createStore(rootReducer, integrateDevTools)
index.jsx:
这样就可以了。
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root'),
)
if (module.hot) {
module.hot.accept()
}
是的,实际上,如果您使用 react-hot-loader,您将获得完全相同的结果,甚至更多。
react-hot-loader
将确保只更新您更改的那三个,并且还会将状态保持在 redux 上。
示例:您正在创建一个模式,它从 API 接收一些信息,然后将信息保留在 redux 上,如果您更改文本颜色,您就知道您'将不得不等待整个应用程序刷新,然后浏览器呈现,然后你必须打开模态,等待 API 等等 BUT 反应热-loader,在您更改该颜色后,您的模式仍将打开,并显示您当前的数据,并且只是该颜色将被更新。
按照软件包自述文件中的步骤进行操作:
1 - 你需要安装这个包(是的,不需要是开发依赖,README 解释了更详细的原因)
npm install react-hot-loader
2 - 添加到.babelrc
// .babelrc
{
"plugins": ["react-hot-loader/babel"]
}
3 - 在App.js
文件的第一行导入hot
(是的,在React,ReactDOM之上,最重要的)然后标记你的根作为热导出的组件
// App.js
import { hot } from 'react-hot-loader/root';
const App = () => <div>Hello World!</div>;
export default hot(App);
就是这样,现在您应该有一个只关注最后更改并为您保持 redux 状态的热重载。
OBS:如果使用hooks,请查看更多详情here on the docs
我使用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()
]
我的 reducers 统计数据:
const initialState = {
...
}
export default function config(state = initialState, action) { ...
我通过以下方式启动我的 Webpack 开发服务器:
"start": "webpack-dev-server",
假设 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 demo.
上看到该方法的实际应用检查与商店创建相关的代码 - 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
只需像下面那样在根元素中呈现应用程序的地方调整您的代码。
store.js:
export const store = createStore(rootReducer, integrateDevTools)
index.jsx:
这样就可以了。
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root'),
)
if (module.hot) {
module.hot.accept()
}
是的,实际上,如果您使用 react-hot-loader,您将获得完全相同的结果,甚至更多。
react-hot-loader
将确保只更新您更改的那三个,并且还会将状态保持在 redux 上。
示例:您正在创建一个模式,它从 API 接收一些信息,然后将信息保留在 redux 上,如果您更改文本颜色,您就知道您'将不得不等待整个应用程序刷新,然后浏览器呈现,然后你必须打开模态,等待 API 等等 BUT 反应热-loader,在您更改该颜色后,您的模式仍将打开,并显示您当前的数据,并且只是该颜色将被更新。
按照软件包自述文件中的步骤进行操作:
1 - 你需要安装这个包(是的,不需要是开发依赖,README 解释了更详细的原因)
npm install react-hot-loader
2 - 添加到.babelrc
// .babelrc
{
"plugins": ["react-hot-loader/babel"]
}
3 - 在App.js
文件的第一行导入hot
(是的,在React,ReactDOM之上,最重要的)然后标记你的根作为热导出的组件
// App.js
import { hot } from 'react-hot-loader/root';
const App = () => <div>Hello World!</div>;
export default hot(App);
就是这样,现在您应该有一个只关注最后更改并为您保持 redux 状态的热重载。
OBS:如果使用hooks,请查看更多详情here on the docs