How to fix Warning: An update to ForwardRef(Component) inside a test was not wrapped in act(...) in React

ReactINTERMEDIATEHIGHUpdated Dec 8, 2025· 113 views

This React Testing Library warning occurs when component state updates happen in tests without proper async handling. The warning indicates untested asynchronous behavior in your components.

Quick fix

Fixes Warning: An update to ForwardRef(Component) inside a test was not wrapped in act(...)

// ❌ Bad - synchronous query
const button = screen.getByRole('button');
fireEvent.click(button);
expect(screen.getByText('Success')).toBeInTheDocument();

// ✅ Good - async query with waitFor
const button = screen.getByRole('button');
fireEvent.click(button);
await waitFor(() => {
  expect(screen.getByText('Success')).toBeInTheDocument();
});

// ✅ Better - use findBy which includes waiting
const button = screen.getByRole('button');
fireEvent.click(button);
expect(await screen.findByText('Success')).toBeInTheDocument();
  1. Use React Testing Library async utilities instead of manual act()
  2. Replace fireEvent with userEvent for user interactions
  3. Wrap async assertions in waitFor()
  4. Handle timers in tests with fake timers
react — error
// ❌ Bad - synchronous query
const button = screen.getByRole('button');
fireEvent.click(button);
expect(screen.getByText('Success')).toBeInTheDocument();
// ✅ Good - async query with waitFor
const button = screen.getByRole('button');
fireEvent.click(button);
await waitFor(() => {
expect(screen.getByText('Success')).toBeInTheDocument();
});
// ✅ Better - use findBy which includes waiting
const button = screen.getByRole('button');
fireEvent.click(button);
expect(await screen.findByText('Success')).toBeInTheDocument();
Warning: An update to ForwardRef(Component) inside a test was not wrapped in act(...)

What this error means

This warning appears when React detects state updates or side effects happening in your test environment that weren't properly awaited or wrapped in the act() utility. React's testing utilities require that all component updates be wrapped in act() to ensure the test waits for updates to complete before making assertions. The warning is React's way of telling you that something asynchronous happened in your component that your test didn't account for. This often occurs with useEffect hooks, timers, async API calls, or event handlers that update state. The warning doesn't mean your code is broken in production, but it indicates your test isn't fully capturing the component's behavior, which could lead to flaky or unreliable tests.

Typical symptoms

  • Warning message appears in test console output
  • Tests pass but show act() warnings
  • Warning references specific component names like ForwardRef or component function names
  • Multiple warnings appear for a single test case
  • Warnings only occur in test environment, not in browser
  • Async state updates happen after test assertions complete
  • useEffect hooks or timers trigger after test finishes

Common causes

  1. Using fireEvent instead of userEvent for interactions that trigger async updates
  2. Not awaiting async operations with waitFor() or findBy queries
  3. State updates in useEffect hooks that run after component renders
  4. setTimeout or setInterval calls that update state asynchronously
  5. API calls or promises that resolve after test assertions
  6. Event handlers that trigger state changes without proper async handling
  7. Third-party components with internal async behavior
  8. Missing cleanup in useEffect causing updates after unmount

How to fix "Warning: An update to ForwardRef(Component) inside a test was not wrapped in act(...)"

1Use React Testing Library async utilities instead of manual act()

React Testing Library provides built-in async utilities that automatically wrap updates in act(). Replace synchronous queries with async alternatives:

javascript
// ❌ Bad - synchronous query
const button = screen.getByRole('button');
fireEvent.click(button);
expect(screen.getByText('Success')).toBeInTheDocument();

// ✅ Good - async query with waitFor
const button = screen.getByRole('button');
fireEvent.click(button);
await waitFor(() => {
  expect(screen.getByText('Success')).toBeInTheDocument();
});

// ✅ Better - use findBy which includes waiting
const button = screen.getByRole('button');
fireEvent.click(button);
expect(await screen.findByText('Success')).toBeInTheDocument();

The findBy queries automatically wait for elements to appear and are wrapped in act().

2Replace fireEvent with userEvent for user interactions

The userEvent library from @testing-library/user-event provides more realistic user interactions and handles async updates properly:

javascript
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';

test('handles button click', async () => {
  const user = userEvent.setup();
  render(<MyComponent />);

  // ❌ fireEvent doesn't wait for async updates
  // fireEvent.click(screen.getByRole('button'));

  // ✅ userEvent properly awaits all updates
  await user.click(screen.getByRole('button'));

  expect(screen.getByText('Updated')).toBeInTheDocument();
});

Always await userEvent methods as they return promises.

3Wrap async assertions in waitFor()

For assertions that depend on async state updates, use waitFor() to wait for the condition to be met:

javascript
import { render, screen, waitFor } from '@testing-library/react';

test('updates after async operation', async () => {
  render(<AsyncComponent />);

  // Trigger the async operation
  const button = screen.getByRole('button');
  await userEvent.click(button);

  // Wait for the update to complete
  await waitFor(() => {
    expect(screen.getByText('Loading complete')).toBeInTheDocument();
  });

  // Or wait for element to appear
  await waitFor(() => {
    expect(screen.queryByText('Loading...')).not.toBeInTheDocument();
  });
});

waitFor() automatically retries the callback until it succeeds or times out.

4Handle timers in tests with fake timers

If your component uses setTimeout or setInterval, use Jest fake timers to control timing:

javascript
import { render, screen, act } from '@testing-library/react';

test('handles delayed state update', async () => {
  jest.useFakeTimers();

  render(<ComponentWithTimeout />);

  // Fast-forward time and flush all pending timers
  await act(async () => {
    jest.runAllTimers();
  });

  expect(screen.getByText('Timeout complete')).toBeInTheDocument();

  jest.useRealTimers();
});

Wrap timer advances in act() to ensure React processes all updates.

5Ensure proper cleanup in useEffect hooks

Missing cleanup functions can cause state updates after component unmount:

javascript
// ❌ Bad - no cleanup, may update after unmount
useEffect(() => {
  fetchData().then(data => setData(data));
}, []);

// ✅ Good - cleanup cancels pending updates
useEffect(() => {
  let cancelled = false;

  fetchData().then(data => {
    if (!cancelled) {
      setData(data);
    }
  });

  return () => {
    cancelled = true;
  };
}, []);

// ✅ Also good - with AbortController
useEffect(() => {
  const controller = new AbortController();

  fetchData(controller.signal)
    .then(data => setData(data))
    .catch(err => {
      if (err.name !== 'AbortError') throw err;
    });

  return () => controller.abort();
}, []);
6Mock async dependencies properly

When mocking API calls or async functions, ensure they resolve synchronously in tests or are properly awaited:

javascript
import { render, screen, waitFor } from '@testing-library/react';

// Mock the API
jest.mock('../api', () => ({
  fetchUser: jest.fn(),
}));

import { fetchUser } from '../api';

test('loads user data', async () => {
  // Mock resolves immediately
  fetchUser.mockResolvedValue({ name: 'John' });

  render(<UserProfile userId="123" />);

  // Wait for the data to load
  expect(await screen.findByText('John')).toBeInTheDocument();

  // Or use waitFor
  await waitFor(() => {
    expect(screen.getByText('John')).toBeInTheDocument();
  });
});
7Use act() manually only when necessary

For rare cases where you need to trigger updates outside React Testing Library utilities:

javascript
import { render, act } from '@testing-library/react';

test('handles external state manager', async () => {
  const { container } = render(<Component />);

  // Manual state update outside React
  await act(async () => {
    externalStore.dispatch({ type: 'UPDATE' });
    // Wait for any promises to resolve
    await new Promise(resolve => setTimeout(resolve, 0));
  });

  expect(container.textContent).toContain('Updated');
});

Only use this as a last resort - prefer React Testing Library's built-in utilities.

Advanced notes

The act() warning is actually a helpful signal from React's test renderer, not just noise to suppress. It indicates that your test isn't fully exercising the component's behavior. When you see this warning, it means there's asynchronous work happening that you're not testing. Suppressing the warning without addressing the root cause can lead to race conditions and flaky tests. In React 18 and later, the act() warning has been refined to reduce false positives, but genuine warnings should still be addressed. For complex components with multiple async operations, consider breaking them into smaller, more testable units. Third-party component libraries may trigger act() warnings due to their internal implementation - in these cases, ensure you're using the latest version of both the library and React Testing Library, as compatibility improvements are ongoing. The React team recommends treating act() warnings with the same seriousness as test failures, as they indicate incomplete test coverage of component behavior.

Frequently asked questions

What does "Warning: An update to ForwardRef(Component) inside a test was not wrap" mean?
This warning appears when React detects state updates or side effects happening in your test environment that weren't properly awaited or wrapped in the act() utility. React's testing utilities require that all component updates be wrapped in act() to ensure the test waits for updates to complete before making assertions. The warning is React's way of telling you that something asynchronous happened in your component that your test didn't account for.
How do I fix "Warning: An update to ForwardRef(Component) inside a test was not wrap"?
This React Testing Library warning occurs when component state updates happen in tests without proper async handling. The warning indicates untested asynchronous behavior in your components.
What causes "Warning: An update to ForwardRef(Component) inside a test was not wrap"?
Using fireEvent instead of userEvent for interactions that trigger async updates Not awaiting async operations with waitFor() or findBy queries State updates in useEffect hooks that run after component renders
Is the "Warning: An update to ForwardRef(Component) inside a test was not wrap" error serious?
Yes. This is a high-severity error that usually blocks work until it is fixed, but the steps above resolve it.

Official resources & further reading