How to Use waitFor in Testing Library in React
Use
waitFor from React Testing Library to wait for asynchronous changes in your React component during tests. Wrap the code that checks for the expected change inside waitFor, which retries until the condition passes or times out.Syntax
The waitFor function takes an async callback that contains assertions or queries. It keeps retrying the callback until it passes or a timeout occurs.
Basic syntax:
await waitFor(() => {
// your assertion or query here
})You can also pass options like timeout to control how long it waits.
javascript
import { waitFor } from '@testing-library/react'; await waitFor(() => { // assertion or query }, { timeout: 1000 });
Example
This example shows a component that fetches data and displays it after a delay. The test uses waitFor to wait until the data appears in the document.
javascript
import React, { useEffect, useState } from 'react'; import { render, screen, waitFor } from '@testing-library/react'; function AsyncComponent() { const [data, setData] = useState(null); useEffect(() => { setTimeout(() => { setData('Hello, world!'); }, 500); }, []); return <div>{data ? data : 'Loading...'}</div>; } // Test test('waits for data to appear', async () => { render(<AsyncComponent />); expect(screen.getByText('Loading...')).toBeInTheDocument(); await waitFor(() => { expect(screen.getByText('Hello, world!')).toBeInTheDocument(); }); });
Output
PASS waits for data to appear
Common Pitfalls
- Not using
awaitwithwaitFor: This causes tests to pass before the async update happens. - Putting non-assertion code inside
waitFor: Only assertions or queries that throw on failure should be inside. - Using
waitForunnecessarily: Use it only when waiting for async UI changes, not for static content.
javascript
/* Wrong way: missing await */ waitFor(() => { expect(screen.getByText('Hello')).toBeInTheDocument(); }); /* Right way: use await */ await waitFor(() => { expect(screen.getByText('Hello')).toBeInTheDocument(); });
Quick Reference
waitFor retries the callback until it passes or times out.
await waitFor(() => { expect(...).toBeInTheDocument() }): Wait for elementtimeoutoption: Customize wait time (default 1000ms)- Use only for async UI updates
Key Takeaways
Always use await with waitFor to properly wait for async UI changes.
Put only assertions or queries that throw inside waitFor's callback.
Use waitFor when your component updates asynchronously, like after data fetching.
Customize timeout if your async updates take longer than default 1000ms.
Avoid using waitFor for static content that appears immediately.