2

大多数人都在寻找如何摆脱act()测试中的反应错误。我想知道相反。我有导致状态变化的代码。该状态更改应该触发react中的重新渲染(确实如此)。但是,我没有 act() 包装该状态更改,并且没有发出 act() 错误。为什么是这样?

考虑以下愚蠢的组件:

export function SweetTextboxBro() {
  const [text, setText] = React.useState("");
  return (
    <>
      <input
        type="text"
        role="input"
        name="sweetbox"
        onChange={(evt) => {
          setText(evt.currentTarget.value);
        }}
        value={text}
      />
      <p>{text}</p>
    </>
  );
}

现在,考虑这个最小的测试:

import * as React from "react";
import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { SweetTextboxBro } from "../SweetTextboxBro";
import { sleep } from "../timing";

test("it emits act errors", async () => {
  render(<SweetTextboxBro />); // should internally call act()
  const textbox = screen.getByRole("input");
  const input = "weeee";
  // begin state change!
  userEvent.type(textbox, input);
  await sleep(200);
  // state updated! the DOM  has changed! but no act() error... is emitted
  expect(await screen.findByText(input)).toBeInTheDocument();
});

当 react 在 act() 调用之外重新渲染内容时,会发生动作错误。我不清楚为什么这种情况不适用。

4

1 回答 1

1

React 测试库包装fireEventuserEventact内部调用。此外,React 会自动处理由点击事件产生的状态变化,这意味着它们act一开始不会触发警告。

act只有在使用作为已解决承诺的结果运行的异步代码时才需要,例如,在进行 API 调用时。

这意味着您甚至不需要await更改测试中的输入。以下测试也将通过。

test("it emits act errors", () => {
  render(<SweetTextboxBro />); // should internally call act()
  const textbox = screen.getByRole("input");
  const input = "weeee";
  userEvent.type(textbox, input);
  expect(screen.getByText(input)).toBeInTheDocument();
});
于 2021-03-07T17:45:14.123 回答