react: "not wrapped in act(...)" warning triggered by an async change in useEffect; Not sure how to fix.
Do you want to request a feature or report a bug?
Not really either; perhaps just an issue with the act
design?
What is the current behavior?
I receive the Warning: An update to ... inside a test was not wrapped in act(...).
warning if a component under test has a useEffect
that makes a change to itself async (I assume because the component updates itself after the act
block)
If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem. Your bug will get fixed much faster if we can run your code and it doesn’t have dependencies other than React. Paste the link to your JSFiddle (https://jsfiddle.net/Luktwrdm/) or CodeSandbox (https://codesandbox.io/s/new) example below:
I think I’ve distilled this as far as I can:
// This is the component under test
function TestComponent() {
const [initialized, setInitialized] = React.useState(false);
// this function would really be a jest mock.fn of an async http request.
// just put it here to simplify the test.
const loadData = () => {
return new Promise(resolve => {
resolve();
});
};
React.useEffect(() => {
initialize();
}, []);
async function initialize() {
await loadData();
setInitialized(true); // <-- this change seems to trigger the `act` warning, but I can't wrap it in an act...
}
return <span>{initialized ? 'loaded' : 'loading...'}</span>;
}
// And this is the test for the above component
beforeEach(() => {
container = document.createElement('div');
document.body.appendChild(container);
});
afterEach(() => {
document.body.removeChild(container);
container = null;
});
test('act works in this case', () => {
act(() => {
ReactDOM.render(<TestComponent />, container);
});
});
What is the expected behavior?
The render is happening within the act, but I’m assuming the setInitialized
is probably being fired async after the act
exits.
I’m not entirely sure how to handle this case, since I can’t put an act
inside the component being tested. Any recommendations or guidance would be much appreciated.
Which versions of React, and which browser / OS are affected by this issue? Did this work in previous versions of React?
"react": "16.8.6",
"react-dom": "16.8.6",
"jest": "24.7.1",
About this issue
- Original URL
- State: closed
- Created 5 years ago
- Reactions: 2
- Comments: 30 (6 by maintainers)
Links to this issue
Commits related to this issue
- Wrap test in async act Rendering the component was resulting in an "Updated outside of act()" warning. Solution from https://github.com/facebook/react/issues/15379#issuecomment-482101020. — committed to johnwcallahan/manager by johnwcallahan 4 years ago
- M3-4107 [Billing] Activity Feed (#6346) * WIP activity feed * Fix component props * Add error handling * Clean up and fix test * Fix props.children in TableContentWrapper * Wrap test i... — committed to linode/manager by johnwcallahan 4 years ago
- Feature/billing redesign (#6417) * M3-4105 billing skeleton (#6336) * Refactor BillingDetail to function component * Clean up and add useStyles() * Remove obsolete test * Add useAccount h... — committed to linode/manager by Jskobos 4 years ago
- Fix test issue https://github.com/facebook/react/issues/15379 — committed to gabalafou/mobile-passhash by gabalafou 4 years ago
- Fix test issue https://github.com/facebook/react/issues/15379 — committed to gabalafou/mobile-passhash by gabalafou 4 years ago
- Fix test issue https://github.com/facebook/react/issues/15379 — committed to gabalafou/mobile-passhash by gabalafou 4 years ago
This is fixed in master; we now have an async version of
act()
. Here’s the original issue, with examples on how async act can scope these updates correctly https://github.com/facebook/react/issues/14769#issuecomment-479942713 . It’s available in 16.9.0-alpha, and will be included in our next release. In your specific case, with the new alpha, this would pass your tests.Closing this issue, but feel free to reach out and comment on the other one.
Having the same issue with
16.12.0
. The workaround withawait act(async () => { ... })
does not get rid of the warning.Is there any workaround to fix this until 16.9.0 is released
Thanks @threepointone but I just wrapped everything in the
act
like this:which seems to work.
@kentcdodds Ok, you motivated me to try again and I was able to make all the tests pass without silencing the warnings. Thanks.
i’m having trouble with typescript however, is there any way to contribute or work around until release?
Wow, awesome, thx!!!
I’m sure the react team would welcome any contributions you can make to improve the warning. My guess is they’re already giving you all the information they have.
Hi @acao, the reason yours is working is because you added
await
there which ensures that you wait until the next tick of the event loop before continuing. That “works” but it could stop working unexpectedly (if you add more async stuff on additional ticks of the event loop). There are better ways to solve this problem. Learn all about this from my blog (and never have a question about this warning again) 😉: https://kentcdodds.com/blog/fix-the-not-wrapped-in-act-warningSure… but what? How about telling us what that ‘something’ is, so that it is easier to figure out? In my case, my library is wrapping another library components and who knows if the problem is in my component or deeper down the chain. Again, help remove the complication somehow.
I was in similar situation, where I was testing a Form component, I mocked the api module and I am changing a loader state from true to false on response of the api, and In the DOM I was disabling a button until response comes from api, and I was getting this “not wrapped in act(…)” warning
solution from https://testing-library.com/docs/react-testing-library/faq works for me, by using findBy* query after submit button gets clicked.
This warning is usually caused by an async operation causing an update after the test has already finished. There are 2 approaches to resolve it:
Wait for the result of the operation in your test by using one of the async utilities like wait or a find* query. For example: const userAddress = await findByLabel(/address/i). Mocking out the asynchronous operation so that it doesn’t trigger state updates. Generally speaking, approach 1 is preferred since it better matches the expectations of a user interacting with your app.
taken from https://testing-library.com/docs/react-testing-library/faq
Can you try: https://medium.com/javascript-in-plain-english/how-to-use-async-function-in-react-hook-useeffect-typescript-js-6204a788a435
Well, from the post:
So if you see the warning, it’s because your test is incomplete. If you use React Testing Library utilities, you very rarely need to use act. So there’s not much to this honestly 🤷♂️
@kentcdodds Thanks for this, but OMG complex. I read your post and my head is still spinning… it makes me not want to write tests at all, which is obviously not a good thing.
In my own project, I ended up just silencing the warnings after a while. Maybe some day I’ll spend the time to figure it out.
Same I’m using 16.9 with @testing-library/react and still running into this!
I updated my react version to 16.9.0-alpha.0 but I am still getting the same warning.
Do I need to update other dependencies? I included my dependency list here.