React's legacy testing utilities have been deprecated in favor of modern testing libraries. This warning appears when using ReactTestUtils or react-dom/test-utils APIs that are scheduled for removal in React 19.
This deprecation warning indicates you're using React's legacy testing utilities (ReactTestUtils or react-dom/test-utils) which have been superseded by more modern testing approaches. React's team officially recommends migrating to React Testing Library for a better-supported and more user-centric testing experience. The deprecation affects multiple APIs: ReactDOMTestUtils.act() has been deprecated in favor of importing act from 'react' directly, renderIntoDocument will be removed in React 19, and most other test utilities have already been removed except for act. React Testing Library provides a more robust testing philosophy that encourages testing components the way users actually interact with them, rather than testing implementation details. This approach leads to more maintainable tests that are less likely to break when refactoring.
If you haven't already, add React Testing Library to your project:
npm install --save-dev @testing-library/react @testing-library/jest-domOr with Yarn:
yarn add --dev @testing-library/react @testing-library/jest-domFor React 18+, ensure you have version 13.0.0 or higher of React Testing Library.
Migrate from ReactTestUtils.renderIntoDocument to React Testing Library's render:
Before:
import ReactTestUtils from 'react-dom/test-utils';
const component = ReactTestUtils.renderIntoDocument(
<MyComponent />
);After:
import { render } from '@testing-library/react';
const { container, getByRole } = render(<MyComponent />);React Testing Library's render returns helpful query functions and automatically handles cleanup.
Replace ReactTestUtils.Simulate with Testing Library's fireEvent or userEvent:
Before:
import ReactTestUtils from 'react-dom/test-utils';
ReactTestUtils.Simulate.click(button);
ReactTestUtils.Simulate.change(input, { target: { value: 'test' } });After (with fireEvent):
import { render, fireEvent } from '@testing-library/react';
const { getByRole } = render(<MyComponent />);
fireEvent.click(getByRole('button'));
fireEvent.change(getByRole('textbox'), { target: { value: 'test' } });Better (with userEvent):
import { render } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
const { getByRole } = render(<MyComponent />);
const user = userEvent.setup();
await user.click(getByRole('button'));
await user.type(getByRole('textbox'), 'test');userEvent simulates real browser interactions more accurately.
If you're using act directly, import it from 'react' instead of 'react-dom/test-utils':
Before:
import { act } from 'react-dom/test-utils';
await act(async () => {
// test code
});After:
import { act } from 'react';
await act(async () => {
// test code
});Note: When using React Testing Library's render and fireEvent, you typically don't need to use act explicitly - it's handled automatically.
Replace ReactTestUtils finder methods with Testing Library queries:
Before:
import ReactTestUtils from 'react-dom/test-utils';
const buttons = ReactTestUtils.scryRenderedDOMComponentsWithTag(
component,
'button'
);
const element = ReactTestUtils.findRenderedDOMComponentWithClass(
component,
'my-class'
);After:
import { render } from '@testing-library/react';
const { getAllByRole, getByText } = render(<MyComponent />);
const buttons = getAllByRole('button');
const element = getByText('My Text'); // or getByTestId('my-test-id')Testing Library encourages querying by role, label, or text rather than implementation details like CSS classes.
Adopt Testing Library's assertion patterns and matchers:
Before:
expect(element.textContent).toBe('Hello');
expect(element.className).toContain('active');After:
import '@testing-library/jest-dom';
expect(element).toHaveTextContent('Hello');
expect(element).toHaveClass('active');jest-dom provides semantic matchers that make tests more readable and provide better error messages. Common matchers include: toBeInTheDocument, toBeVisible, toBeDisabled, toHaveAttribute.
After migrating, run your tests to ensure everything works:
npm testCheck that:
- All deprecation warnings are gone
- Tests pass with the same coverage
- Console is clear of React warnings
If you see any remaining warnings, search your codebase for remaining ReactTestUtils imports:
grep -r "react-dom/test-utils" src/
grep -r "ReactTestUtils" src/Migration Strategy for Large Codebases:
You don't have to migrate all tests at once. Install React Testing Library alongside existing test utilities and adopt a policy where new tests use Testing Library exclusively. Gradually refactor old tests during normal maintenance.
Handling Third-Party Dependencies:
Some packages may internally use deprecated React testing utilities. Check for updates to those packages, or consider alternatives if updates aren't available. Tools like npm-check-updates can help identify outdated dependencies.
Testing Philosophy Shift:
React Testing Library promotes testing user behavior rather than implementation details. Instead of accessing component state or props directly, test what users see and do. Query by accessible roles (button, textbox, heading) rather than CSS classes or test IDs when possible.
Common Patterns:
- Use screen queries (from @testing-library/react) for most queries to avoid destructuring
- Prefer getByRole over getByTestId when elements have semantic HTML
- Use waitFor for async behavior instead of manual act() calls
- Setup jest-dom matchers globally in your test setup file
React 19 Timeline:
The complete removal of react-dom/test-utils APIs (except React.act) is planned for React 19. Migrating now ensures your tests won't break when upgrading to future React versions.
TypeScript Considerations:
Update @types/react to 18.3.1 or higher to get proper TypeScript support for React.act. Earlier versions may show type errors when importing act from 'react'.
React Hook useCallback has a missing dependency: 'variable'. Either include it or remove the dependency array react-hooks/exhaustive-deps
React Hook useCallback has a missing dependency
Cannot use private fields in class components without TS support
Cannot use private fields in class components without TS support
Cannot destructure property 'xxx' of 'undefined'
Cannot destructure property of undefined when accessing props
useNavigate() may be used only in the context of a <Router> component.
useNavigate() may be used only in the context of a Router component
Cannot find module or its corresponding type declarations
How to fix "Cannot find module or type declarations" in Vite