This rule raises an issue when a call to act only wraps calls to React Testing Library or user-event utilities.
React’s act() testing helper makes sure that all updates related to a "unit" of interaction, such as a render, a user event, or a
state update, have been processed and applied to the DOM before assertions run. Calling React APIs directly, such as ReactDOM.render or
dispatching a raw DOM event, can leave pending updates unflushed, which is why act() exists.
React Testing Library builds this guarantee in for you: render, fireEvent, the userEvent API, and the async
utilities waitFor and waitForElementToBeRemoved are already wrapped in act() internally. Wrapping a call to one
of these utilities in another act() does not change what gets flushed and does not make the test more correct, it just adds noise around
code that is already safe.
Developers often add an unnecessary act() wrapper to silence a "not wrapped in act(…)" warning. That warning is not incidental: it
usually means a state update happened outside of any tracked render, for example because of an unawaited asynchronous callback, a timer, or a
subscription firing after the test moved on. Wrapping the wrong piece of code in act() hides the warning without addressing what caused
it, so the underlying issue can resurface later as a flaky or genuinely broken test.
Remove the redundant act() call and use the Testing Library utility directly; it already flushes its own updates. If an
act() warning remains after removing the wrapper, act() should be moved to wrap the actual source of the untracked update
instead, such as a manual timer advance or a call into non-Testing-Library code, rather than the Testing Library call itself.
import { render, screen, fireEvent, act } from '@testing-library/react';
test("submits the form", () => {
act(() => { // Noncompliant: "render()" already wraps itself in "act()"
render(<Form />);
});
act(() => { // Noncompliant: "fireEvent" already wraps itself in "act()"
fireEvent.click(screen.getByRole('button'));
});
});
import { render, screen, fireEvent } from '@testing-library/react';
test("submits the form", () => {
render(<Form />);
fireEvent.click(screen.getByRole('button'));
});
act