You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React StrictMode下reducer重复调用及组件更新报错求助

保留React StrictMode的解决方案

1. 关于StrictMode下Reducer被调用两次的说明

React StrictMode会双调用纯函数(包括reducer、useState初始化函数等),目的是检测代码中是否存在隐藏的副作用。只要你的reducer是纯函数(不修改外部状态、不执行异步操作、相同输入返回相同输出),这种双调用是完全安全的,属于正常行为,不需要特殊处理。你的valueReducer满足纯函数要求,所以这个现象可以忽略。

2. 解决Cannot update a component while rendering a different component错误

这个错误的根源是你的ValueProvider中多余的useState和useEffect包装,导致context值更新时机异常,引发组件渲染期间的状态更新冲突。

错误原因分析

你当前的Provider中,用useState保存contextValue,再通过useEffect监听state变化来更新它——这完全是冗余操作。useReducer返回的dispatch是组件生命周期内稳定的引用,state会随着dispatch自动更新,直接将{state, dispatch}作为context值即可,不需要额外的状态包装。

修改后的ValueProvider代码

export const ValueContext = createContext<ValueContextState>({
    state: getDefaultState(),
    dispatch: () => {},
});

export const ValueProvider = ({ children }: Props) => {
    const [state, dispatch] = useReducer<React.Reducer<ValueState, ValueActions>>(valueReducer, getDefaultState());

    // 直接组合state和dispatch作为context值,无需额外useState和useEffect
    const contextValue = { state, dispatch };

    return <ValueContext.Provider value={contextValue}>{children}</ValueContext.Provider>;
};

function getDefaultState(): ValueState {
    return {
        value: null,
    };
}

type Props = {
    children: React.ReactNode;
};

3. 其他代码的优化建议

  • 你的useValues自定义hook可以保持不变,因为dispatch现在是稳定引用,useCallback的依赖不会频繁变化。
  • 确保InputComponent的onChange回调是在事件处理阶段执行(而非渲染阶段),你的当前写法是正确的,setValue在输入变化时触发,属于事件处理,不会引发渲染期间的更新。

完成以上修改后,既可以保留StrictMode的开发检测能力,又能解决调试时的组件更新错误,同时reducer的双调用属于正常StrictMode行为,不影响功能。

内容的提问来源于stack exchange,提问作者maxfromgermany

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 04:54:10