Resolving React Test act
Deprecation Warnings
Problem Statement
When testing React components with Jest and React Testing Library, developers often encounter this warning:
"Warning: An update to [Component] inside a test was not wrapped in act(...)."
Despite following this instruction, your IDE may flag the act
method as deprecated when using React 18+, causing confusion about correct implementation. The core issues are:
- React 18's state batching changes
- Outdated Testing Library dependencies
- Incorrect
act
imports - Conflicts between testing packages
Recommended Solutions
1. Update Testing Library Dependencies
Primary Fix: Upgrade to compatible versions that support React 18's act
changes:
npm install @testing-library/react@^15.0.6
npm install @types/react@18.3.1
Compatibility Notes
- Requires React ≥18.3.1
- Fixes type declarations and prevents deprecated warnings (Release Notes)
2. Correct Import for act
Import from React’s package instead of testing utils:
- import { act } from '@testing-library/react'
+ import { act } from 'react'
3. Eliminate Conflicting Packages
Uninstall deprecated libraries causing type conflicts:
npm uninstall react-test-renderer
Updated Test Example
import '@testing-library/jest-dom';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { act } from 'react'; // Correct import
import ContactFormController from '.';
describe('Contact Form Controller tests', () => {
it('renders loader and disables submit on form submit', async () => {
render(<ContactFormController />);
const submitBtn = screen.getByTestId('contact-submit-button');
// Wrap interactions in act
await act(async () => {
await userEvent.type(screen.getByLabelText(/First Name/i), 'Captain');
await userEvent.type(screen.getByLabelText(/Last Name/i), 'Bob');
await userEvent.type(screen.getByLabelText(/Email/i), 'captain@bob.com');
await userEvent.type(
screen.getByPlaceholderText(/Greetings/i),
'Captain Ahoy'
);
await userEvent.click(submitBtn);
});
expect(screen.getByRole('alert')).toBeInTheDocument();
expect(submitBtn).toBeDisabled();
});
});
Key Improvements:
- Uses
screen
for queries (Best Practice) - Adds
await
to alluserEvent
interactions - Corrects
act
import source
Why These Solutions Work
Dependency Updates:
React 18.3.1+ exportsact
via the mainreact
package. Newer React Testing Library versions resolve type conflicts with this change.Async Event Handling:
ModernuserEvent
methods are asynchronous. Usingawait
ensures state updates complete before assertions.IDE Warning Resolution:
Upgraded@types/react
provides accurate TypeScript definitions matching React's API changes.
Final Recommendations
- Update routinely: Keep alignment between React and Testing Library versions.
- Avoid unnecessary
act
: Most user interactions and queries handleact
internally. Only use explicitact
for uncontrolled state updates. - Use Testing Library's
waitFor
for complex async flows instead of manualact
wrapping.
React 18 Testing Rules
- Automatic batching handles most common scenarios
- Manual
act
is required only for non-user-triggered updates (e.g., timers, external subscriptions) - Use
await userEvent
for interactions
By updating dependencies and adjusting imports, you eliminate deprecation warnings while ensuring tests validate component behavior correctly.