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
相关产品推荐
相关产品推荐

