动态添加Redux Reducer后,react-redux <Provider>状态缺失问题排查
这个问题其实是Redux动态添加reducer后的常见坑——你添加了reducer,但还没触发任何action让store初始化这个reducer对应的状态分支。
为什么会出现这个情况?
Redux的全局state是由根reducer处理action时生成的。当你调用store.reducerManager.add()把新reducer加入后,根reducer确实更新了,但此时没有任何action被触发,所以根reducer并不会主动去调用新添加的reducer来生成初始状态。
当你的<UDP>组件挂载时,connect会立即执行一次mapStateToProps,此时store的state还是添加reducer之前的快照——自然找不到state[ownProps.campaign.campaignId]。只有当之后有任意action被dispatch(比如组件内部的action,或者其他地方的更新),store才会用新的根reducer计算完整的state,这时新reducer的初始状态才会被加入到全局state中,mapStateToProps第二次执行就能拿到正确的值了。
解决方法
有两种简单的方式可以解决这个问题:
1. 添加reducer后手动触发初始化action
添加完reducer后,dispatch一个Redux内部的@@INIT action(或者自定义一个空action),强制store重新计算state,初始化新reducer的状态:
store.reducerManager.add(campaign.campaignId, UDP.getReducer()); // 触发初始化action,让新reducer返回初始状态并加入全局state store.dispatch({ type: '@@INIT' }); return (<UDP campaign={campaign}/>);
@@INIT是Redux启动时自动触发的action类型,所有reducer都会处理它来返回自己的初始状态,所以用它是安全的,不会影响其他已有的state分支。
2. 在mapStateToProps中做容错处理
如果不想额外dispatch action,可以在获取状态时给一个默认值,避免第一次执行时出现undefined:
const mapStateToProps = (state, ownProps) => { console.log('[stt]', state) // 当状态不存在时,使用默认值兜底 const campaignState = state[ownProps.campaign.campaignId] ?? { isActing: false }; return({ language: state.appstate.language, currentViewData: state.appstate.currentViewData, currentView: state.appstate.currentView, connectedStampId: state.bluetooth.connectedStampId, isBTConnected: state.bluetooth.isBTConnected, isActing: campaignState.isActing, }) }
额外注意点
确保你的reducerManager实现是正确的:它应该在添加reducer后,重新生成根reducer(比如用combineReducers合并最新的reducer map),并且store使用的是这个动态更新的根reducer。从你打印的reducer map来看这部分应该没问题,但如果后续还有问题,可以检查这一步是否正确。
内容的提问来源于stack exchange,提问作者Taata

