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

React自定义异步setState Hook失效,await后无法获取更新状态

解决React中useAsyncState await后仍获取旧state的问题

问题背景

想要通过await处理setState的异步操作,确保后续动作在state更新完成后执行。基于React+TypeScript编写了自定义Hook useAsyncState,但调用await setTest2()后,console.log(test2)输出的仍是未更新的旧值。

自定义Hook代码:

import { useState, useRef, useEffect } from 'react';

const useAsyncState = <T>(initialState: T): [state: T, setState: (newState: T) => Promise<unknown>] => {
  const [state, setState] = useState<T>(initialState);
  const resolveState = useRef<(updated: T) => void>();

  useEffect(() => {
    if (resolveState.current) {
      resolveState.current(state);
      resolveState.current = undefined;
    }
  }, [state]);

  const setAsyncState = (newState: T) =>
    new Promise(resolve => {
      resolveState.current = resolve;
      setState(newState);
    });

  return [state, setAsyncState];
};

export default useAsyncState;

使用示例:

const [test2, setTest2] = useAsyncState<string>('');

const onFunc = async () => {
  await setTest2('新值');
  console.log(test2); // 输出旧值
};

问题原因

React的state具有不可变性,且组件在重新渲染前,当前函数作用域内捕获的state变量不会更新。尽管await setTest2()等待了state更新流程完成,但onFunc函数里的test2仍是当前渲染周期的旧值——新的state要等到组件重新渲染后,才会生成对应的新变量。

解决方法

方法1:让setAsyncState返回新的state值

修改自定义Hook,让setAsyncState的Promise直接返回更新后的state值,这样await后就能直接拿到新值:

import { useState, useRef, useEffect } from 'react';

const useAsyncState = <T>(initialState: T): [state: T, setState: (newState: T | ((prev: T) => T)) => Promise<T>] => {
  const [state, setState] = useState<T>(initialState);
  const resolveState = useRef<(updated: T) => void>();

  useEffect(() => {
    if (resolveState.current) {
      resolveState.current(state);
      resolveState.current = undefined;
    }
  }, [state]);

  const setAsyncState = (newState: T | ((prev: T) => T)) =>
    new Promise<T>(resolve => {
      setState(prev => {
        // 同时处理直接传值和函数式更新两种情况
        const updatedState = typeof newState === 'function' ? (newState as (prev: T) => T)(prev) : newState;
        resolve(updatedState);
        return updatedState;
      });
    });

  return [state, setAsyncState];
};

export default useAsyncState;

使用方式调整为:

const [test2, setTest2] = useAsyncState<string>('');

const onFunc = async () => {
  const updatedState = await setTest2('新值');
  console.log(updatedState); // 输出新值
};

方法2:用useEffect监听state变化

如果后续逻辑需要依赖组件渲染后的最新state,可以通过useEffect监听state的变化,在回调中执行逻辑:

const [test2, setTest2] = useAsyncState<string>('');

// 监听test2变化,更新后执行逻辑
useEffect(() => {
  console.log(test2); // 输出新值
}, [test2]);

const onFunc = async () => {
  await setTest2('新值');
};

内容的提问来源于stack exchange,提问作者고윤태

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 09:13:16