React-testing-library: useEffect with async function call causes `act(...)` warning

Created on 13 May 2020  路  4Comments  路  Source: testing-library/react-testing-library

When rendering and testing a component with a useEffect that calls an async function that modifies the component's state, then an act() console error will be output when running tests.

  • @testing-library/react version: 10.0.4
  • jest version: 26.0.1
  • DOM Environment: jsdom version: 16.2.2

Relevant code or config:

const MyComponent = () => {
    const [loaded, setLoaded] = useState(false)

    useEffect(() => {
        async function load() {
            await loadFromApi()
            setLoaded(true)
        }
        load()
    }, [])

    return loaded ? <div>loaded</div> : <div>loading...</div>
}

// timeout=0 to simulate mocked api responses
const loadFromApi = () => new Promise(resolve => setTimeout(resolve, 0))

What you did:

Just render this component in a jest test.

test('act() console error', () => {
    const sut = render(<MyComponent />)
    expect(sut).toBeDefined()
})

What happened:

This error is output in my project when running tests:

  console.error
    Warning: An update to null inside a test was not wrapped in act(...).

    When testing, code that causes React state updates should be wrapped into act(...):

Reproduction:

See console output:
https://codesandbox.io/s/react-testing-library-demo-sk2so

Problem description:

Rendering should wait until everything has been resolved.

Suggested solution:

Since async functions inside useEffect are quite common, rendering a component containing such a hook should wait for the component updates to have finished (with a small timeout).

Most helpful comment

Hi @fabb,

There's no way for React Testing Library to know that you've got async stuff happening in the background, and you wouldn't want that anyway because you probably want to assert the "loading" state anyway.

This is why React Testing Library gives you async utils which you can use to wait for the UI to update asynchronously.

Here's how you'd fix that codesandbox: https://codesandbox.io/s/react-testing-library-demo-dmklb?file=/src/__tests__/hello.js:244-306

The cool thing about this is the async utils provided by React Testing Library are automatically wrapped in act so you shouldn't ever have to worry about using act manually. Learn more here: https://kcd.im/act-warning

Good luck :)

All 4 comments

Hi @fabb,

There's no way for React Testing Library to know that you've got async stuff happening in the background, and you wouldn't want that anyway because you probably want to assert the "loading" state anyway.

This is why React Testing Library gives you async utils which you can use to wait for the UI to update asynchronously.

Here's how you'd fix that codesandbox: https://codesandbox.io/s/react-testing-library-demo-dmklb?file=/src/__tests__/hello.js:244-306

The cool thing about this is the async utils provided by React Testing Library are automatically wrapped in act so you shouldn't ever have to worry about using act manually. Learn more here: https://kcd.im/act-warning

Good luck :)

Thanks for looking into this. I guess I need to find out what I need to wait for. Let鈥榮 go hunting 馃槄

BTW thanks for the tip of updating jest to include a backtrace in the error log output, that helps a lot.

Hi @fabb,

There's no way for React Testing Library to know that you've got async stuff happening in the background, and you wouldn't want that anyway because you probably want to assert the "loading" state anyway.

This is why React Testing Library gives you async utils which you can use to wait for the UI to update asynchronously.

Here's how you'd fix that codesandbox: https://codesandbox.io/s/react-testing-library-demo-dmklb?file=/src/__tests__/hello.js:244-306

The cool thing about this is the async utils provided by React Testing Library are automatically wrapped in act so you shouldn't ever have to worry about using act manually. Learn more here: https://kcd.im/act-warning

Good luck :)

OMG I was stuck with this warning for 24 hours. Thank you for your help, this worked.

Was this page helpful?
0 / 5 - 0 ratings