React useState状态更新不生效:调用函数时未获取更新后的值
React useState更新后立即使用状态值未更新的原因及解决办法
原因分析
- React的
useState状态更新是异步批量处理的,调用setisValid后,状态不会立刻同步更新到当前函数的变量中。 - 函数
GetData是在当前渲染周期创建的,它的闭包捕获的是当前渲染时的isValid初始值(false)。哪怕setisValid已经执行,在这个函数里直接访问isValid还是旧值。 - 调试器里看到的
isValid为true,是因为调试器会读取组件最新的状态,但这和当前函数闭包里保留的旧变量不是同一个引用。
解决办法
办法1:直接使用判断后的结果(最简便)
既然已经通过type.isValid === "true"得到了要设置的布尔值,直接把这个值传给GetMyData,不用依赖状态变量:
const GetData = () => { const newIsValid = type.isValid === "true"; setisValid(newIsValid); GetMyData(ID, newIsValid) .then((response) => { if (componentMounted.current) { const apiResult: ApiResult<ItemApproval> = response.data; if (!apiResult?.success && apiResult?.message) { onError("Checking validity", apiResult?.message ?? "Error retrieving state value"); } setData(apiResult.data); } }) .catch(function (error: any) { console.log("Error in GetData: ", error); if (componentMounted.current) { onError("Error", "Error retrieving state"); } }); };
办法2:用useEffect监听状态变化
如果必须依赖更新后的状态值触发请求,可以把GetMyData的调用放到useEffect中,监听isValid的变化:
useEffect(() => { // 这里的isValid是更新后的最新值 GetMyData(ID, isValid) .then((response) => { if (componentMounted.current) { const apiResult: ApiResult<ItemApproval> = response.data; if (!apiResult?.success && apiResult?.message) { onError("Checking validity", apiResult?.message ?? "Error retrieving state value"); } setData(apiResult.data); } }) .catch(function (error: any) { console.log("Error in GetData: ", error); if (componentMounted.current) { onError("Error", "Error retrieving state"); } }); }, [isValid, ID, onError]); // 根据实际业务添加必要依赖 const GetData = () => { setisValid(type.isValid === "true"); };
办法3:用useRef同步最新状态(可选)
如果需要在函数里随时获取最新状态,可以用useRef同步状态值:
const isValidRef = useRef(false); const [isValid, setisValid] = useState(false); // 同步ref和状态 useEffect(() => { isValidRef.current = isValid; }, [isValid]); const GetData = () => { const newIsValid = type.isValid === "true"; setisValid(newIsValid); isValidRef.current = newIsValid; // 手动同步ref GetMyData(ID, isValidRef.current) .then((response) => { if (componentMounted.current) { const apiResult: ApiResult<ItemApproval> = response.data; if (!apiResult?.success && apiResult?.message) { onError("Checking validity", apiResult?.message ?? "Error retrieving state value"); } setData(apiResult.data); } }) .catch(function (error: any) { console.log("Error in GetData: ", error); if (componentMounted.current) { onError("Error", "Error retrieving state"); } }); };
内容的提问来源于stack exchange,提问作者StackTrace
相关产品推荐
相关产品推荐

