首页 > 解决方案 > 测试 React 组件 -> setInterval

问题描述

我的目标是测试从 60 秒倒计时到 0 的简单组件,然后运行一个函数。

共同点:

import { useEffect, useState } from "react";

export default function Clock({ dispatch }) {
  const [clock, setClock] = useState(60);
  useEffect(() => {
    const tick = setInterval(() => {
      setClock(clock - 1);
    }, 1000);
    if (clock === 0) {
      dispatch({ type: "breakDone" });
    }
    return function cleanUp() {
      clearInterval(tick);
    };
  });
  console.log(clock);
  return (
    <div className="clock__container">
      <h1>{clock}s</h1>
      <p data-testid="clock-paragraph">
        lorem ipsum
      </p>
    </div>
  );
}

我在测试组件时遇到问题。我尝试用不同的方法对其进行测试,但是我的计时器从未下降到 59 秒。

我厌倦了什么:

  1. 给出最差的反馈 -> 假阳性
  test("Value of clock after 1s", async () => {
    render(<Clock />);
    expect(screen.getByText("60s")).toBeInTheDocument();
    setTimeout(() => {
      expect(screen.getByText("59s")).toBeInTheDocument();
    }, 1000);
  });
 test("Value of clock after 1s", async () => {
    render(<Clock />);
    expect(screen.getByText("60s")).toBeInTheDocument();
    jest.advanceTimersByTime(10000);
    expect(await screen.findByText("59s")).toBeInTheDocument();
  });
  1. 该解决方案正确地测试了 1 秒的保证,但在 10 秒时失败。
  test("Value of clock after 1s", async () => {
    render(<Clock />);
    const headerElement = screen.getByRole("heading");
    jest.advanceTimersByTime(1000);
    await waitFor(() => expect(headerElement.innerHTML).toBe("59s"));
  });

老实说,我不知道问题是什么。

标签: reactjsreact-testing-library

解决方案


你的 useEffect 钩子需要一个时钟状态的依赖数组

像这样:

useEffect(() => {
    const tick = setInterval(() => {
      setClock(clock - 1);
    }, 1000);
    if (clock === 0) {
      dispatch({ type: "breakDone" });
    }
    return function cleanUp() {
      clearInterval(tick);
    };
  },[clock]);

推荐阅读