effects
useInsertionEffect
Runs before any DOM mutations from the current render are applied, giving CSS-in-JS libraries a chance to inject <style> tags first. Reach for it only if you are authoring a styling library — application code should not use it.
useInsertionEffect(setup, dependencies?) Parameters & Behavior
| Parameter | Purpose |
|---|---|
| setup | Side effect that runs before layout effects can read the DOM |
| dependencies | Same rules as useEffect — re-runs when deps change |
| no ref access | You cannot read refs here — they aren't populated yet |
| no state updates | Scheduling updates here is not allowed at this stage of commit |
Examples
useInsertionEffect(() => {
const style = document.createElement('style');
style.textContent = rule;
document.head.appendChild(style);
return () => style.remove();
}, [rule]); Inject a dynamic style rule before any layout effect measures the DOM
useInsertionEffect(() => {
cache.insert(className, cssText);
}, [className, cssText]); Emotion/styled-components style caches use this pattern internally
// Library code only — application components should call useLayoutEffect or useEffect instead. Guidance: reserve for style-injection primitives
useInsertionEffect(() => { registerTheme(themeVars); return () => unregisterTheme(themeVars); }, [themeVars]); Register CSS custom properties for a theme before layout runs
Gotcha
Refs are not yet attached and you cannot schedule updates — this is a narrow hook meant for style injection. Introduced in React 18; misuse produces subtle timing bugs.
Related hooks
useLayoutEffect
Runs a side effect synchronously after DOM mutations but before the browser paints. Reach for it only when you need to measure the DOM and then mutate it in a way the user must never see mid-flight (e.g. tooltip positioning).
useEffect
Runs a side effect after the browser has painted the committed render. Reach for it for subscriptions, data fetching, DOM syncing with external systems, timers, and anything that must not block the visual update.
useId
Generates a unique, stable string ID that is consistent between server and client renders. Reach for it whenever you need to associate elements (label htmlFor, aria-describedby) without collisions in an SSR-safe way.