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

使用react-hooks-testing-library测试含useEffect的Hook时useEffect未触发

为什么测试中的useEffect始终不触发?

你的自定义钩子和测试代码存在几个核心问题,直接导致了useEffect无法触发:

1. 自定义钩子不能是异步函数

你定义的useCustomHook是async function,但React钩子必须是同步函数。异步函数会破坏React钩子的调用规则,导致React无法正确识别并处理其中的useEffect,这是useEffect不触发的根本原因之一。

2. 函数调用逻辑错误

callRemote是useEffect回调内部的局部函数,你却在useEffect外部直接调用它——这不仅会抛出callRemote is not defined的错误,也完全违背了React副作用的设计逻辑,useEffect的回调本身都没机会执行。

3. 使用了SSR版本的renderHook

你导入的是@testing-library/react-hooks/server的renderHook,这个工具专门用于测试服务器端渲染的钩子,默认会跳过所有客户端副作用(包括useEffect),因为SSR环境中React不会执行这类客户端专属的副作用代码。

4. 测试断言时机不对

即使前面的问题都修复,你的测试直接断言data.isAuthenticated为true,但someApi是异步操作,断言会在异步请求完成前执行,不仅会失败,也无法验证useEffect的执行效果。


修复后的示例代码

修正后的自定义钩子

import { useEffect } from 'react';

export function useCustomHook(data) {
  useEffect(() => {
    console.log('useEffect called');

    async function callRemote() {
      const isAuthenticated = await someApi();
      data.isAuthenticated = isAuthenticated;
    }

    callRemote(); // 在useEffect内部调用异步函数
  }, [data]);
}

修正后的测试代码

import { renderHook, waitFor } from "@testing-library/react-hooks";
import { useCustomHook } from '../useCustomHook';

// 模拟异步API
jest.mock('../someApi', () => ({
  __esModule: true,
  default: jest.fn().mockResolvedValue(true)
}));

test('it should set data obj', async () => {
  const dataMock = {};
  renderHook(() => useCustomHook(dataMock));

  // 等待异步操作完成后再断言
  await waitFor(() => {
    expect(dataMock.isAuthenticated).toBe(true);
  });
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 16:06:42