How to Mock Concurrent Mode in React

Testing React applications that utilize Concurrent Mode and features like transitions can be difficult due to their non-blocking, asynchronous nature. This article explains how to mock React’s concurrent features, such as useTransition and useDeferredValue, using Jest to make your component tests run predictably and synchronously.

Why Mock Concurrent Mode?

Concurrent features in React (introduced in React 18) de-prioritize certain state updates to keep the main thread responsive. During a transition, React may prepare the new UI in the background while keeping the current UI visible.

In a testing environment, this non-blocking behavior can cause race conditions or assertion failures because your assertions may execute before the lower-priority background update completes. Mocking these hooks forces React to process these updates synchronously, eliminating flakiness.

Mocking useTransition

The useTransition hook returns an isPending boolean and a startTransition function. To mock this hook so that it runs synchronously, you can override its behavior using Jest.

import React from 'react';

jest.mock('react', () => {
  const actualReact = jest.requireActual('react');
  return {
    ...actualReact,
    useTransition: () => [false, (callback) => callback()],
  };
});

How It Works:

Mocking useDeferredValue

The useDeferredValue hook defers updating a part of the UI. To mock it so that it returns the new value instantly without any lag or deferral, use the following mock:

import React from 'react';

jest.mock('react', () => {
  const actualReact = jest.requireActual('react');
  return {
    ...actualReact,
    useDeferredValue: (value) => value,
  };
});

How It Works:

Complete Mocking Template

If your test suite requires mocking both concurrent hooks, you can combine them into a single Jest mock block at the top of your test file:

import { render, screen, fireEvent } from '@testing-library/react';
import React from 'react';
import MyComponent from './MyComponent';

// Mock concurrent features globally for this test file
jest.mock('react', () => {
  const actualReact = jest.requireActual('react');
  return {
    ...actualReact,
    useTransition: () => [false, (cb) => cb()],
    useDeferredValue: (value) => value,
  };
});

test('should render updates synchronously', () => {
  render(<MyComponent />);
  
  const button = screen.getByRole('button');
  fireEvent.click(button);
  
  // Assertions will now pass immediately without needing complex async helpers
  expect(screen.getByText('Updated Content')).toBeInTheDocument();
});