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

测试使用useEffect、useReducer的自定义hook时出现act警告如何解决

这个警告的产生原因是你使用的waitForNextUpdate没有自动将promise resolve后触发的dispatch状态更新包裹进React要求的act测试上下文,导致状态更新发生在React的测试追踪范围外,以下是三种可行的解决方法,按推荐优先级排序:


方案1:使用waitFor替代waitForNextUpdate(最推荐)

waitFor是测试库官方更推荐的异步等待工具,会自动将内部涉及的所有状态更新包裹在act中,同时会自动重试断言直到超时。你可以直接把原测试中的等待和断言逻辑合并,修改后测试代码如下:

// 先从测试库引入waitFor
import { waitFor } from '@testing-library/react-hooks'

describe('[Hook] useJobs', () => {
  const httpServiceInstance = new HttpService();
  it.only('Should return jobs when response is successful', async () => {
    const response: IApiResponse<Job[]> = {
      status: 200,
      response: [mockJob()],
    };

    jest
      .spyOn(httpServiceInstance, 'get')
      .mockImplementation(() => Promise.resolve(response));

    const wrapper = ({ children }: { children?: React.ReactNode }) => (
      <HttpContext.Provider value={httpServiceInstance}>
        {children}
      </HttpContext.Provider>
    );
    const { result } = renderHook(() => useJobs(), {
      wrapper,
    });

    // 替换原来的waitForNextUpdate + 单独断言
    await waitFor(() => {
      expect(result.current).toEqual([mockJob()]);
    })
  });
});

方案2:手动用act包裹异步等待逻辑

如果你暂时需要保留waitForNextUpdate的写法,可以手动用异步act包裹等待逻辑,强制将后续的状态更新纳入测试上下文:

import { act } from '@testing-library/react-hooks'

// ...其他代码不变
const { result, waitForNextUpdate } = renderHook(() => useJobs(), { wrapper });

await act(async () => {
  await waitForNextUpdate();
})

expect(result.current).toEqual([mockJob()]);

方案3:React 18+项目迁移到官方内置的renderHook

如果你使用的是React 18及以上版本,@testing-library/react-hooks已经被官方废弃,你可以直接使用@testing-library/react内置的renderHook,新版本的测试工具会自动处理所有异步状态更新的act包裹,不需要额外手动修改逻辑即可消除警告。


额外优化提示:你的hook中httpService.get().then()的回调函数标记了async但内部没有任何await逻辑,可以把这个多余的async去掉,避免不必要的异步层级。

内容的提问来源于stack exchange,提问作者Lucas Ezequiel Ojeda

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 13:54:03