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

React Context中状态始终为初始值的原因探究

React Context中state.value始终打印初始值的原因解析

问题现象

在学习React Context机制时,编写了如下Context Provider代码:

import React, { createContext, useState } from "react";

interface myState {
  value: number;
  setValue: Function;
}

export const MyContext = createContext<myState | null>(null);

export const MyContextProvider = ({
  children,
}: {
  children: React.ReactNode;
}) => {
  const setValue = (newVal: number) => {
    console.log(state.value); // 始终打印初始值10,而非更新后的值
    setState((prevState) => {
      return {
        ...prevState,
        value: newVal,
      };
    });
  };

  const [state, setState] = useState({
    value: 10,
    setValue: setValue, // 将初始的setValue存入state
  });

  return <MyContext.Provider value={state}>{children}</MyContext.Provider>;
};

调用setValue更新值后,console.log(state.value)始终打印初始值10,而非实际更新后的数值。

核心原因:闭包陷阱

这是典型的React闭包陷阱问题:

  • 组件首次渲染时,创建了setValue函数,此时它捕获了当前的state(初始值{value:10, setValue: ...})。
  • 这个初始的setValue被存入了state对象中,后续调用setState更新value时,state里的setValue始终是首次渲染时的那个函数。
  • 每次组件重新渲染,虽然会生成新的setValue函数(它能捕获最新的state),但Context Provider传递的state里的setValue还是旧的闭包函数,它只能访问到首次渲染时的state.value。

解决方案:传递最新的setValue到Context

将Provider的value改为动态生成的对象,每次渲染都传入最新的setValue函数:

return (
  <MyContext.Provider
    value={{
      ...state,
      setValue: setValue, // 每次渲染都传入最新的setValue
    }}
  >
    {children}
  </MyContext.Provider>
);

这样,Context消费组件拿到的setValue始终是当前渲染周期的最新函数,它捕获了最新的state,调用时就能打印出正确的state.value。

如果注释掉setValue: setValue这一行,Provider的value会复用state里的旧setValue,闭包未更新,问题就会重现。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 08:55:04