How to Mock useLayoutEffect Hook in React
Testing React components that utilize the
useLayoutEffect hook in testing environments like Jest
often triggers console warnings, specifically the “useLayoutEffect does
nothing on the server” warning. This article provides a quick,
straightforward guide on how to mock the useLayoutEffect
hook to eliminate these warnings and ensure your unit tests run
smoothly.
Why Mock useLayoutEffect?
The useLayoutEffect hook fires synchronously after all
DOM mutations but before the browser paints. Because test runners like
Jest run in a simulated browser environment (JSDOM) powered by Node.js,
React detects that it is not running in a real browser and outputs a
warning.
To prevent this clutter in your test suite, you can mock
useLayoutEffect to behave exactly like
useEffect during testing.
Method 1: Mocking Globally in Jest (Recommended)
The cleanest way to handle this warning is by mocking the hook
globally in your Jest setup file (usually jest.setup.js or
setupTests.js). This applies the fix to all tests
automatically.
Add the following line to your Jest setup file:
import React from 'react';
jest.spyOn(React, 'useLayoutEffect').mockImplementation(React.useEffect);If you only want to apply this mock to a specific test file, you can place this exact code block at the very top of that specific test file.
Method 2: Creating a Custom Safe Hook
If you prefer not to touch your Jest configuration, you can solve the
issue within your source code by creating a custom hook that
conditionally uses useEffect or
useLayoutEffect depending on the runtime environment.
Create a helper hook:
import { useEffect, useLayoutEffect } from 'react';
export const useSafeLayoutEffect =
typeof window !== 'undefined' ? useLayoutEffect : useEffect;Inside your components, import and use
useSafeLayoutEffect instead of React’s default
useLayoutEffect. This naturally bypasses the warning during
server-side rendering and testing environments without requiring Jest
mocks.
Method 3: Inline Jest Mocking
If you are using standard jest.mock to mock module-level
exports, you can mock the React module directly at the top of your test
file:
import React from 'react';
jest.mock('react', () => ({
...jest.requireActual('react'),
useLayoutEffect: jest.requireActual('react').useEffect,
}));This approach overrides useLayoutEffect with
useEffect specifically for the test file it is declared in,
allowing your tests to render components without console errors.