修改Redux Store后组件未刷新问题排查:修改JSON文件数据后connect函数触发但组件未重建
问题排查:Redux状态更新但组件未重新渲染
你完全找对了方向——就是不可变性的问题导致组件没重新渲染!
咱们来看你的reducer代码里的关键问题:
let DELETE_C_newChordOrder = state.mesures[action.mesure].chordOrder DELETE_C_newChordOrder.splice(action.index, 1)
这里DELETE_C_newChordOrder只是原数组的引用,并没有创建新数组。而splice是直接修改原数组的方法,哪怕你后面用展开运算符拷贝了外层的mesures和对应小节对象,但chordOrder还是原来的那个数组引用。
Redux判断状态是否变化的核心是对比引用:如果新旧状态里的某个值引用没变化,它就会认为这部分状态没更新,自然不会触发组件的重新渲染。
修复方案有两种,选你顺手的就行:
方案1:先拷贝原数组再修改
先通过展开运算符创建原数组的副本,再对副本进行splice操作,这样就能保证返回的是新数组引用:
function songReduceur(state = initialState, action) { switch (action.type) { case CONSTANTS.DELETE_CHORD: // 先拷贝原数组,生成新引用 const DELETE_C_newChordOrder = [...state.mesures[action.mesure].chordOrder] DELETE_C_newChordOrder.splice(action.index, 1) return { ...state, mesures:{ ...state.mesures, [action.mesure]: { ...state.mesures[action.mesure], chordOrder: DELETE_C_newChordOrder } } } default: return state } } export default songReduceur
方案2:用filter生成新数组(更简洁的不可变操作)
filter方法天生会返回一个新数组,不需要手动拷贝,代码更简洁:
function songReduceur(state = initialState, action) { switch (action.type) { case CONSTANTS.DELETE_CHORD: return { ...state, mesures:{ ...state.mesures, [action.mesure]: { ...state.mesures[action.mesure], // filter返回排除指定索引后的新数组 chordOrder: state.mesures[action.mesure].chordOrder.filter((_, idx) => idx !== action.index) } } } default: return state } } export default songReduceur
记住一个核心原则:Redux的状态更新必须是不可变的——任何修改都要返回新的对象/数组引用,绝对不能直接修改原状态。这样connect才能正确检测到状态变化,触发组件重新渲染。
内容的提问来源于stack exchange,提问作者Gabriel Pouzargue
相关产品推荐
相关产品推荐

