React: When To Use act()
2023-03-04
React
testing
best practices
Jest
Long story short
In another article before (React: Why Not To Use act() (In Most Of The Cases)), I've outlined why the act() is probably not something one should use when faced with a "not wrapped in act(...)" warning in tests using React Testing Library (TL;DR most of the React Testing Library functions are already wrapped in act() internally).
But then, why does it exist and when to use it? There's a long and detailed article on the subject: https://kentcdodds.com/blog/fix-the-not-wrapped-in-act-warning#other-use-cases-for-manually-calling-act but in short, when the status update in the code executed asynchronously is not going to be executed within React's callstack - for instance,
- When using
jest.useFakeTimers()
to manipulate the timers and timer-controlled functionality, so e.g.jest.advanceTimersByTime(1000)
should be called asact(() => jest.advanceTimersByTime(1000))
(there's a detailed example in the aforementioned article). - When testing custom hooks: if a hook returns a function that could manage a state later, its call might need to be wrapped in act() as
act(() => result.current.functionThatSetsState())
for theconst {result} = renderHook(() => useHookThatReturnsStaetSetterFunction())
. - When using
useImperativeHandle
hook - I'm not familiar with it, but to quote the article, "you only run into this if you're calling methods directly on a component which do internal state updates and you're outside of React's callstack".