Người Malaysia đến Việt Nam nhận ra: hóa ra Người Việt Nam gầy không phải do nghèo!
Người Malaysia đến Việt Nam nhận ra: hóa ra Người Việt Nam gầy không phải do nghèo!

When should I use act() in react-testing-library?

You don’t need to use act() because most of the cases are already wrapped in act().

TL;DR;

  • wrapped in act()if I faced some errors related toact(). And if that doesn’t work, I suffered because it didn’t work even I used async-await.
  • userEventor some event functions are already wrapped in act fromtesting-library/react, therefore you don’t need to useact()actually. (👉 code)

First things first, I wrapped in act()…

When I joined the current company 5 months ago, there is no tests on the code that I am in charge of, so I set up using testing-library/react, and msw. And I am adding tests one by one.

One of the frequent mistakes I often make is, first things first, I wrapped things in act(). I read Common mistake with React Testing Library a few days ago, I would like to write this article about act().

what they don’t know is that

renderandfireEventare already wrapped inact!

What does act() do?

act() takes in a function as its first argument and called it to apply to the DOM(jsdom). Afteract() function is executed, you can make assertions so it helps make tests run closer to what real users would experience.

However, it’s quite verbose when you use act() directly from react-dom/test-utils. It would be better to use act() from testing-library/react to avoid some of the boilerplate.

Please refer to the below to take a look at what act() looks like.

  • React (act is born here)
  • testing-library/dom (provides configure function for testing DOM)
  • react-testing-library (overrides with new function wrapped in act() using configure function from testing-library/dom)

test(‘Testing’, () => {
act(() => {
/* Codes you want to apply to the DOM */
(e.g. ReactDOM.render(<Counter />, container);)
}); /* assume that the code is applied to the DOM */
});

Just focus on the basic logic, except complex things, act returns thenable object after calling a callback function.

However, I don’t know exactly when I can use this object.

You don’t need to use act() actually.

The reason why you don’t need to do is the most of cases like userEvent, render are wrapped in act already.

eventWrapper() in testing-library/dom is called when event functions like userEvent.click are invoked to make changes to jsdom. testing-library/react overrides eventWrapper() so the event functions are executed in act().

import { configure as configureDTL } from ‘@testing-library/dom’;
import act from ‘./act-compat’;// overriedconfigureDTL({
eventWrapper: cb => { // like userEvent.click()
let result; act(() => {
result = cb();
}); return result;
},
})

Therefore you don’t have to wrap any event like userEvent with act().


act(() => {
userEvent.click(screen.getByText(‘Component’));
});✅
userEvent.click(screen.getByText(‘Component’));

Plus, testing-library/react wrap render with act so you don’t have to go out of your way to use it again 😅

function render(ui, { hydrate = false, …rest }) {
(…) act(() => {
if (hydrate) {
ReactDOM.hydrate(wrapUiIfNeeded(ui), container)
} else {
ReactDOM.render(wrapUiIfNeeded(ui), container)
}
}) (…)
}

act calls can be nested, so React team tracks the depth of act() with the variable actScopeDepth based on the stack. But I think it might be able to make unexpected results by wrapping things in act unnecessarily so Kent C. said we don’t need to do.

You are watching: When should I use act() in react-testing-library?. Info created by GBee English Center selection and synthesis along with other related topics.