深度克隆Redux状态后修改,为何开发环境不触发重渲染?
Redux开发环境下组件不触发重渲染(仅Next.js开发环境存在,生产正常)
Redux Slice 代码
export const mealPlanSlice = createSlice({ name: "mealPlanner", initialState, reducers: { addOrUpdatePlan: addOrUpdate, } }) export const { addOrUpdatePlan } = mealPlanSlice.actions; export default mealPlanSlice.reducer;
对应的Reducer逻辑
import clone from "just-clone"; export const addOrUpdate = ( state: IMealPlanState, action: PayloadAction< { date: DateString } & { components: { recipeId: RecipeUuid; componentId: ComponentUuid; servingsIncrease: number; }[]; } > ) => { const newState = clone(state); const { date, components } = action.payload; for (const { recipeId, componentId, servingsIncrease } of components) { if (newState.plan[date]) { if (recipeId in newState.plan[date]) { const componentIndex = newState.plan[date][recipeId].findIndex( (mealPlanItem) => mealPlanItem.componentId === componentId ); if (componentIndex > -1) { const component = newState.plan[date][recipeId][componentIndex]; const newServings = component.servings + servingsIncrease; if (newServings > 0) { newState.plan[date][recipeId][componentIndex].servings = newServings; } else { newState.plan[date][recipeId].splice(componentIndex, 1); if (newState.plan[date][recipeId].length === 0) { delete newState.plan[date][recipeId]; } } } else { newState.plan[date][recipeId].push({ componentId, servings: servingsIncrease, }); } } else { newState.plan[date][recipeId] = [ { componentId, servings: servingsIncrease, }, ]; } } } return newState; };
Store配置
export const store = configureStore<IFullStoreState>({ reducer: { printing, plants, food, mealPlan, user, }, });
订阅状态的组件代码
const Recipes = () => { const mealPlan = useSelector((store) => store.mealPlan.plan); return ... }
问题现象与排查信息
- Redux DevTools显示状态变更正确,新老状态各层级均不浅相等,但分发action后组件不触发重渲染
- 项目中多个Slice都存在此问题
- 仅在Next.js开发构建环境出现,生产部署后问题消失
原因分析
- Next.js Fast Refresh机制冲突:开发环境的Fast Refresh会保留组件状态,可能与Redux的订阅逻辑兼容异常。当组件通过
useSelector引用深层状态对象时,Fast Refresh可能未正确识别状态变更带来的组件依赖变化。 - 深度克隆工具的潜在兼容问题:
just-clone在开发环境下可能与TypeScript类型或Next.js工具链存在兼容问题,导致克隆后的状态对象出现未预期的引用/结构问题(虽已确认状态差异,但仍需验证)。 - Redux DevTools开发增强的延迟:开发环境下Redux DevTools的增强器会对状态做额外处理,偶尔会导致状态变更通知延迟。
解决方案建议
- 给
useSelector添加自定义深比较函数,强制识别深层状态变化:import isEqual from 'lodash/isEqual'; const mealPlan = useSelector((store) => store.mealPlan.plan, isEqual); - 替换
just-clone为原生structuredClone,规避第三方库的兼容问题:const newState = structuredClone(state); - 临时禁用Fast Refresh测试,确认是否为其导致:
// next.config.js module.exports = { fastRefresh: false, }; - 检查Redux、React-Redux与Next.js的版本兼容性,避免版本不匹配引发的开发环境异常。
内容的提问来源于stack exchange,提问作者George Sheppard
相关产品推荐
相关产品推荐

