为啥在 Redux-DevTools 中使用 Webpack HMR 插件时 App 状态会重置?
Posted
技术标签:
【中文标题】为啥在 Redux-DevTools 中使用 Webpack HMR 插件时 App 状态会重置?【英文标题】:Why does App state resets when using Webpack HMR plugin with Redux- DevTools?为什么在 Redux-DevTools 中使用 Webpack HMR 插件时 App 状态会重置? 【发布时间】:2016-10-22 18:13:09 【问题描述】:我正在使用带有 Redux Devtools Chrome 扩展的 webpack Hot Module Replacement(HMR) 插件。但是,每当 HMR 运行时,Redux 本地应用程序状态都会重置为所有初始值。我的网络配置如下:
import webpack from 'webpack'
import path from 'path'
import htmlWebpackPlugin from 'html-webpack-plugin'
const LAUNCH_COMMAND = process.env.npm_lifecycle_event
const isProduction = LAUNCH_COMMAND === 'production'
process.env.BABEL_ENV = LAUNCH_COMMAND
const PATHS =
app: path.join(__dirname, 'app'),
build: path.join(__dirname, 'dist')
const HTMLWebpackPluginConfig = new HtmlWebpackPlugin(
template: PATHS.app + '/index.html',
filename: 'index.html',
inject: 'body'
)
const productionPlugin = new webpack.DefinePlugin(
'process.env':
NODE_ENV: JSON.stringify('production')
)
const productionPlugin2 = new webpack.optimize.UglifyJsPlugin(
compressor:
warnings: false
)
const base =
entry: [
'babel-polyfill',
PATHS.app
],
output:
path: PATHS.build,
filename: 'index_bundle.js'
,
module:
loaders: [
test: /\.js$/, exclude: /node_modules/, loader: 'babel-loader',
test: /\.css$/, loader: 'style!css?sourceMap&modules&localIdentName=[name]__[local]___[hash:base64:5]'
]
,
resolve:
root: path.resolve('./app')
const developmentConfig =
devtool: 'cheap-module-inline-source-map',
devServer:
contentBase: PATHS.build,
historyApiFallback: true,
hot: true,
inline: true,
progress: true
,
plugins: [HTMLWebpackPluginConfig, new webpack.HotModuleReplacementPlugin()]
const productionConfig =
devtool: 'cheap-module-source-map',
plugins: [HTMLWebpackPluginConfig, productionPlugin, productionPlugin2]
export default Object.assign(, base, isProduction === true ? productionConfig : developmentConfig)
这是我的主要应用 index.js 的样子:
import React from 'react'
import ReactDOM from 'react-dom'
import getRoutes from './config/routes'
import createStore, applyMiddleware, compose, combineReducers from 'redux'
import Provider from 'react-redux'
import authUser, unauthUser, fetchingUserSuccess from 'redux/modules/users'
import ReduxThunk from 'redux-thunk'
import initAuth, formatUserInfo from 'helpers/auth'
import * as reducers from 'redux/modules'
let reducer = combineReducers(reducers)
// const store = createStore(
// reducer,
// compose(applyMiddleware(ReduxThunk),
// window.devToolsExtension ? window.devToolsExtension() : f => f))
function configureStore ()
const store = createStore(
reducer,
compose(applyMiddleware(ReduxThunk),
window.devToolsExtension ? window.devToolsExtension() : f => f))
if (module.hot)
module.hot.accept('redux/modules', () =>
store.replaceReducer(require('redux/modules').default)
)
return store
const store = configureStore()
export function checkAuth (nextState, replace)
// debugger
// console.log('isAuthed from Main container mount')
// const isAuthed = checkIfAuthed(store)
const isAuthed = store.getState().users.isAuthed
// const isAuthed = store.getState().isAuthed
console.log('isAuthed from checkAuth method', isAuthed)
const nextPathName = nextState.location.pathname
console.log('nextPathName', nextPathName)
// debugger
if ((isAuthed !== true) && (nextPathName !== 'auth'))
// debugger
console.log('replaced path to auth')
replace('auth')
else if ((nextPathName === '/' || nextPathName === 'auth') && (isAuthed === true))
// debugger
console.log('replaced path to feed')
replace('feed')
initAuth()
.then((user) =>
if (user !== null)
console.log('intial user', user.displayName)
store.dispatch(authUser(user.uid))
const userInfo = formatUserInfo(user.displayName, user.photoURL, user.uid)
store.dispatch(fetchingUserSuccess(user.uid, userInfo))
else
console.log('intial user is :', user)
store.dispatch(unauthUser())
ReactDOM.render(
<Provider store = store>
getRoutes(checkAuth)
</Provider>,
document.getElementById('app')
)
)
.catch((error) =>
console.log('ERROR', error)
)
【问题讨论】:
【参考方案1】:在你的 App index.js 中移除这个方法
if (module.hot)
module.hot.accept('redux/modules', () =>
store.replaceReducer(require('redux/modules').default)
)
【讨论】:
我最近刚刚添加了这个 sn-p 代码,因为有人告诉我它可以让它工作。它没有或没有你要求我删除的这个 sn-p。如果您注意到 configureStore 函数正上方,我有一个注释代码。我还通过注释 configureStore 函数并取消注释上面的代码来运行它,我只是使用 createStore 创建一个常量存储【参考方案2】:即使我无法复制问题(欢迎使用 jsfiddle),更换后更新商店应该会有所帮助:
if (module.hot)
module.hot.accept('redux/modules', () =>
store.replaceReducer(require('redux/modules').default)
if (window.devToolsExtension) window.devToolsExtension.updateStore(store)
)
【讨论】:
【参考方案3】:使用redux-persist 通过页面刷新操作和选项卡或浏览器关闭来保持应用程序状态。
【讨论】:
以上是关于为啥在 Redux-DevTools 中使用 Webpack HMR 插件时 App 状态会重置?的主要内容,如果未能解决你的问题,请参考以下文章
P06:Chrome插件 Redux-DevTools 用来调试Redux数据
Angular NGRX - 为 Redux-Devtools 命名 store/app-instance
将 redux-devtools 传递给带有中间件的 redux 存储