useInsertionEffect Hook — Optimizing CSS-in-JS Libraries
useInsertionEffect is a special React hook that appeared in React 18. It's designed for CSS-in-JS libraries (e.g., styled-components, Emotion, JSS, etc.) to ensure that CSS styles are injected into the DOM at the right time — before rendering.
This is a performance hook that allows React to prevent "unstyled flash" — when a component appears on screen without its CSS and only gets styled a second later.
🔹 How It Works
React's rendering process can be divided into three phases:
- Render Phase — React calculates what to render (Virtual DOM).
- Commit Phase (before paint) — React prepares to update the DOM.
- Paint Phase — browser displays changes on screen.
useInsertionEffect works exactly at the beginning of the commit phase — before React writes DOM changes, meaning before useLayoutEffect.
📍 When to Use It
- If you're writing a CSS-in-JS library (like styled-components).
- If you want to programmatically inject CSS or `<style>` tags without flicker.
- If you need to ensure new DOM elements have their correct CSS even before rendering.
📍 Example 1 — Basic Structure
Here's how the hook is used in React:
import React, { useInsertionEffect } from 'react';
export default function StyledBox() {
useInsertionEffect(() => {
const style = document.createElement('style');
style.innerHTML = `
.styled-box {
background: linear-gradient(45deg, #2196f3, #21cbf3);
color: white;
padding: 20px;
border-radius: 8px;
transition: all 0.3s ease;
}
.styled-box:hover {
transform: scale(1.05);
}
`;
document.head.appendChild(style);
return () => {
document.head.removeChild(style);
};
}, []);
return <div className="styled-box">Beautiful styled box 💎</div>;
}
In this example, CSS is injected into the DOM before rendering, meaning when the component renders, it's already styled without visible flicker.
📍 Example 2 — Comparison with useEffect
Let's see what difference it makes if we do the same with `useEffect` instead of `useInsertionEffect`:
useEffect(() => {
const style = document.createElement('style');
style.innerHTML = '.red { color: red; }';
document.head.appendChild(style);
}, []);
In this case, the style will be added only after React renders the component. This means the user might see unstyled, unformatted UI for half a second ("unstyled flash").
useInsertionEffect solves exactly this problem — injecting CSS before browser paint.
🧠 When Not to Use useInsertionEffect
This hook is not intended for regular programmers. If you're not writing a CSS-in-JS library or framework, you'll likely never need to use it.
- Don't use it for network requests or state changes.
- Don't write async code here (fetch, timeout, etc.).
- Don't add heavy DOM operations — it will slow down rendering.
⚙️ Technical Details
- Runs before useLayoutEffect.
- Works only during client-side rendering.
- Created specifically for libraries to keep CSS insertion synchronous.
This hook doesn't return any value. It only performs a "side effect" — helping React inject CSS at the right time.
🎯 Exercise (Try it yourself)
Write a component that:
- Uses useInsertionEffect to add custom CSS styles to the head.
- Displays text that's colored by that CSS.
- Try doing the same with useEffect and notice the flicker difference.
📘 Summary
- useInsertionEffect — React 18 hook designed for CSS-in-JS libraries.
- Runs immediately after render but before DOM paint.
- Helps avoid flicker and ensures consistent styling.
- Shouldn't be used for regular business logic.