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)

Commits related to this issue

Most upvoted comments

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.

test('act works in this case', async () => {
    await act(async () => {
      ReactDOM.render(<TestComponent />, container);
    });
  });

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 with await 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:

    await act(async () => {
      const { getByText } = render(
        <Provider store={store}>
          <MyComponent />
        </Provider>
      );

      expect(getByText("My component title"));
    });

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-warning

Sure… 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

Well, from the post:

So the act warning from React is there to tell us that something happened to our component when we weren’t expecting anything to happen.

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.

"dependencies": {
    "@material-ui/core": "^4.2.0",
    "@material-ui/icons": "^4.2.1",
    "axios": "^0.19.0",
    "client-oauth2": "^4.2.4",
    "enzyme": "^3.10.0",
    "enzyme-adapter-react-16": "^1.14.0",
    "react": "^16.9.0-alpha.0",
    "react-dom": "^16.9.0-alpha.0",
    "react-redux": "^7.1.0",
    "react-router-dom": "^5.0.1",
    "react-scripts": "3.0.1",
    "react-test-renderer": "^16.9.0-alpha.0",
    "redux": "^4.0.1",
    "redux-thunk": "^2.3.0"
  }