@ryvora/react-use-layout-effect
Version:
ππ Synchronous layout effect hook for React. Measure and update before paint!
52 lines (37 loc) β’ 2.11 kB
Markdown
# use-layout-effect ππ
Hey DOM Measurer! π§
The `use-layout-effect` hook is a version of `useEffect` that fires **synchronously** after all DOM mutations. This is crucial when you need to read layout from the DOM (like getting an element's size or position) and then synchronously re-render based on that information before the browser has a chance to paint.
It's like `useEffect`, but it gets to cut in line πΆββοΈβ‘οΈπΆββοΈ to do its work _before_ the user sees any visual updates!
## `useEffect` vs `useLayoutEffect`
- **`useEffect`**: Runs _asynchronously_ after render and after the browser has painted. Good for most side effects (data fetching, subscriptions).
- **`useLayoutEffect`**: Runs _synchronously_ after render but _before_ the browser paints. Good for DOM measurements that need to trigger a synchronous re-render.
**Warning:** Because `useLayoutEffect` is synchronous, it can block visual updates if you do too much work in it. Prefer `useEffect` when possible!
## When to Use It:
- Measuring DOM elements (e.g., getting `getBoundingClientRect()`).
- Manually changing the DOM (though this should be rare in React) and needing to ensure it's done before paint.
- Animating based on layout changes.
## Basic Usage:
```tsx
import React, { useState, useLayoutEffect, useRef } from 'react';
function MyComponent() {
const [width, setWidth] = useState(0);
const myDivRef = useRef<HTMLDivElement>(null);
useLayoutEffect(() => {
// This runs after the div is rendered but before the browser paints
if (myDivRef.current) {
console.log('Measuring width in useLayoutEffect');
setWidth(myDivRef.current.offsetWidth);
}
// If setWidth here causes a re-render, it happens synchronously
}, []); // Empty array means it runs once after initial layout
return (
<div>
<div ref={myDivRef} style={{ width: '50%', border: '1px solid black' }}>
I am a div!
</div>
<p>The div's calculated width is: {width}px</p>
</div>
);
}
```
Use it wisely to keep your UI snappy and avoid visual flickers! β¨π¨