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

