use-after-paint-effect
Version:
React hook that runs an effect only after at least one paint has occurred. (DOM element is mounted and the first render is complete) Great for starting CSS transitions after first render.
38 lines (35 loc) • 1.66 kB
text/typescript
type AfterPaintCleanup = void | (() => void);
type AfterPaintEffect = () => AfterPaintCleanup;
type AfterPaintEffectDeps = React.DependencyList;
/**
* useAfterPaintEffect
* -------------------
* Like `useEffect`, but your `effect` runs only **after at least one real paint**:
* React commit → layout effects → requestAnimationFrame (pre-paint) → browser paint → effect()
*
* Use this to flip "enter" classes or start CSS transitions **after the element
* has actually appeared on screen once**, avoiding transition-from-default glitches.
*
* @param effect A function invoked after the paint. It may return a cleanup
* function; that cleanup will run on dependency change or unmount,
* mirroring `useEffect` semantics.
* @param deps Dependency list controlling when the effect re-schedules. Same
* rules as `useEffect`.
*
* @example
* // Flip a class after first paint to start a CSS transition
* function Card() {
* const [active, setActive] = React.useState(false);
* useAfterPaintEffect(() => { setActive(true); }, []);
* return (
* <div className={active ? "card card--enter" : "card"} />
* );
* }
*
* @remarks
* - Uses rAF → setTimeout(0) to ensure one paint occurs before `effect`.
* - Cleans up pending rAF/timeout if dependencies change or the component unmounts.
* - In React 18 dev Strict Mode, the mount/unmount/mount cycle is handled safely.
*/
declare function useAfterPaintEffect(effect: AfterPaintEffect, deps: AfterPaintEffectDeps): void;
export { type AfterPaintCleanup, type AfterPaintEffect, type AfterPaintEffectDeps, useAfterPaintEffect };