What does the useInsertionEffect() hook do?
Briefly: what useInsertionEffect() does
useInsertionEffect() is a hook that runs synchronously before the browser applies styles and performs layout, that is, even earlier than useLayoutEffect().
It's needed so libraries can:
- insert CSS rules into the DOM before the browser paints the page;
- avoid a "flash of unstyled content" (FOUC) when generating CSS dynamically;
- guarantee style consistency under concurrent rendering (React 18).
Syntax
useInsertionEffect(() => {
// synchronous insertion of styles or other side effects, before layout
}, [deps]);In terms of interface, it's similar to useEffect and useLayoutEffect, but it runs before all React effects, literally before the browser paints the screen.
1. Why it's needed (and for whom)
Before React 18, CSS-in-JS libraries (for example, Emotion, styled-components, JSS):
- generated classes and inserted styles into
- used useLayoutEffect() for this.
The problem:
Under Concurrent Rendering, React can start a render, pause it, and then continue, which led to styles being inserted at the wrong time, or even multiple times, creating artifacts and flickering content.
useInsertionEffect() solves this: it runs during the "commit" phase, before layout and before painting, so the styles are guaranteed to be inserted before the browser draws anything.
2. Order of hook execution
Here's the order in which React calls the effects:
| Hook | When it runs | Main purpose |
|---|---|---|
| useInsertionEffect | Before layout and before paint | Inserting styles / synchronous operations before painting |
| useLayoutEffect | After the DOM commit, but before paint | Measurements, positioning, synchronous DOM changes |
| useEffect | After paint (asynchronously) | Side effects, subscriptions, logic |
This way:
useInsertionEffect → useLayoutEffect → useEffect
3. Example (simulating how CSS-in-JS works)
import { useInsertionEffect } from "react";
function DynamicStyle({ color }) {
useInsertionEffect(() => {
const style = document.createElement("style");
style.textContent = `.dynamic-text { color: ${color}; }`;
document.head.appendChild(style);
return () => {
document.head.removeChild(style);
};
}, [color]);
return <p className="dynamic-text">Hello, world!</p>;
}Here:
- the style is inserted into before React draws the DOM;
- the user never sees "unstyled" text;
- when the color changes, the old styles are removed.
4. Difference from other effects
| Hook | Timing | Can it cause reflow/paint? | Use it for |
|---|---|---|---|
| useEffect | After painting | can | Subscriptions, requests, side effects |
| useLayoutEffect | After the DOM commit, before paint | can cause reflow | Measurements, DOM manipulation |
| useInsertionEffect | Before layout, before paint | no | Inserting styles, library-level effects |
5. Features
You should not use useInsertionEffect in ordinary applications. This hook is intended only for libraries that insert CSS synchronously.
React guarantees that useInsertionEffect effects run in the order of the component tree hierarchy: this prevents duplication or races when generating classes.
You cannot read layout or the DOM inside useInsertionEffect. Its job is insertion, not measurement. Use useLayoutEffect for measurements.
6. A real-world usage example (Emotion)
useInsertionEffect(() => {
const sheet = document.head.querySelector('#emotion-styles');
sheet.insertRule(`.css-${hash} { color: ${color}; }`);
}, [hash, color]);This logic lets the library insert CSS "on the fly" before the browser renders, without flicker or artifacts during transitions.
7. Summary
useInsertionEffect() is a low-level, synchronous hook that runs even before layout and paint, so libraries can insert dynamic styles into the DOM in time, ensuring a stable appearance even under concurrent rendering.
In brief
| Property | Value |
|---|---|
| Runs | Before useLayoutEffect and useEffect |
| SSR compatible | Yes |
| Intended for | CSS-in-JS libraries (Emotion, styled-components, JSS, etc.) |
| Can it read the DOM? | No |
| Can it modify the DOM (e.g. insert | Yes |
| Works with concurrent rendering | Yes |
| Supported since | React 18+ |
Short Answer
Interview readyA concise answer to help you respond confidently on this topic during an interview.