How to Implement useInsertionEffect in React
In this article, you will learn how to implement the
useInsertionEffect hook in React. We will cover its
specific use case—injecting dynamic CSS-in-JS styles into the DOM before
layout effects trigger—explain why it is crucial for performance, and
provide a practical code example demonstrating its usage.
What is useInsertionEffect?
useInsertionEffect is a React hook introduced in React
18. It is designed exclusively for authors of CSS-in-JS libraries. The
hook fires synchronously before any layout effects
(useLayoutEffect) run and before the browser paints the
screen. This timing allows you to inject <style>
elements into the document head before React calculates the layout of
the DOM.
Why Use It Instead of useLayoutEffect?
Using useLayoutEffect or useEffect to
inject styles dynamically causes performance issues. If you insert
<style> tags during those phases, the browser is
forced to recalculate the layout (a process known as “style recalc” or
“reflow”) multiple times. By using useInsertionEffect, you
ensure that styles are injected before React does any layout passes,
preventing expensive layout recalculations.
How to Implement useInsertionEffect
To implement useInsertionEffect, import it from React
and use it to insert your style rules. Note that you do not have access
to refs inside this hook, and it should not be used for general side
effects like fetching data or updating state.
Here is a practical implementation example:
import React, { useInsertionEffect } from 'react';
// Helper function to insert styles into the document head
function insertStyleRule(rule) {
const style = document.createElement('style');
style.textContent = rule;
document.head.appendChild(style);
}
function MyStyledComponent() {
useInsertionEffect(() => {
const rule = `.dynamic-btn { background-color: #0070f3; color: white; padding: 10px; border: none; }`;
insertStyleRule(rule);
}, []); // Empty dependency array ensures this runs once when the component mounts
return <button className="dynamic-btn">Click Me</button>;
}
export default MyStyledComponent;Hook Execution Order
To understand exactly when this hook runs, here is the chronological order of React’s effect hooks:
useInsertionEffect: Runs before DOM mutations and layout calculations. Best for dynamic style injection.useLayoutEffect: Runs after DOM mutations but before the browser paints. Best for reading DOM layout (like measuring element size).useEffect: Runs after the browser has painted the screen. Best for general side effects like data fetching and event listeners.