无法在Vitest中测试时间相关React自定义Hook问题求助
React useInterval Hook测试时回调未执行的问题解决
问题根源
你的自定义Hook里存在一个关键错误:使用useCallback定义了更新savedCallback的逻辑,但这个函数从未被调用,导致savedCallback.current始终为undefined,当setInterval触发tick函数时,无法执行传入的回调。
原Hook中这段代码只是创建了缓存函数,没有执行逻辑:
useCallback(() => { savedCallback.current = callback; }, [callback]);
修复后的useInterval Hook
将更新savedCallback的逻辑替换为useEffect,这样每当callback变化时,会自动更新ref的current值:
// useInterval.ts import { useEffect, useRef } from "react"; function useInterval(callback: () => void, delay: number | null) { const savedCallback = useRef<typeof callback>(); // 用useEffect监听callback变化,自动更新ref useEffect(() => { savedCallback.current = callback; }, [callback]); useEffect(() => { function tick() { savedCallback.current?.(); } if (delay !== null) { const id = setInterval(tick, delay); return () => clearInterval(id); } }, [delay]); } export default useInterval;
测试代码验证
修复Hook后,原测试逻辑可正常运行。若要验证回调调用次数,可调整断言:
// useInterval.test.ts import { vi, expect, beforeEach, it, afterEach } from "vitest"; import { renderHook } from "@testing-library/react"; import useInterval from "./useInterval"; describe("useInterval", () => { beforeEach(() => { vi.useFakeTimers(); }); afterEach(() => { vi.useRealTimers(); }); test("should call the callback specified times within time range", () => { const mockCallback = vi.fn(); const delay = 100; renderHook(() => useInterval(mockCallback, delay)); vi.advanceTimersByTime(200); expect(mockCallback).toHaveBeenCalledTimes(2); }); });
额外说明
useCallback的作用是缓存函数引用,多用于传递给子组件避免重渲染,或作为其他hooks的依赖。此处需要的是自动更新ref,useEffect是更合适的选择。- 测试时务必在前后切换真实计时器,避免影响其他测试用例。
内容的提问来源于stack exchange,提问作者singhAmandeep007
相关产品推荐
相关产品推荐

