Unexpected uses of useLayoutEffect
Going from animation libraries to galaxy brain state hack

Search for a command to run...
Going from animation libraries to galaxy brain state hack

No comments yet. Be the first to comment.
Redesigning a personal website can feel like an endless loop of trial and error. After several failed attempts to upgrade my site to something more modern, I finally found success by collaborating with an AI tool. Here's how I transformed my website ...

Eleventy is a great static site generator and one of the best parts of it is The Data Cascade. It's a notably simple way to map data to templates and I mean that in the best possible Simple Made Easy sense. I hope more static site generators steal it...

Svelte and TailwindCSS are kinda weird together aren't they? Svelte has this awesome built in styling capability but Tailwind will have you mostly ignore it, since "no custom CSS" while using it is a virtue. The best practice for production builds is...

The docs describe useLayoutEffect as a DOM targeted escape hatch for visual updates to the UI. Why then is a hook like this showing up in:
useSyncExternalStoreuseEvent hook addition?My answer is that there seems to be an emergent use case of useLayoutEffect, one that takes advantage of when it happens to run the React update process. I'd describe it as a lifecycle hook for other hooks. To understand why, let's look at the original use case for useLayoutEffect.
Here is the ordering for when React updates the DOM and when effects run.

React explicitly yields the main thread to let the browser paint the frame. This is a departure from the old component lifecycle componentDidMount but it is in most cases what you want and more performant for synchronization effects that don't immediately have visual updates.
When you do have visual updates, however, doing them in the useEffect can cause flicker in the UI. useLayoutEffect offers an escape hatch for this:

This is the original use case and animation libraries like Framer Motion make use of it for performant animations.
There is another important property of useLayoutEffect, however: It runs before useEffect:

Why is this important? It's for the use case of setting up non-rendering infrastructure across components. Effects and event handlers need to operate on the latest references, for example, but updating them in the render body is impure and useEffect may be too late. Although hooks have explicit execution order within a component, there is no guarantee in React that a particular component will update before any other.
I did not write any of these examples but here is my stab at why useLayoutEffect was used in:
useSelector implementation: Essentially 'initializes' the selector by updating references for event handlers/effects, creating the subscription and evaluating it again on the update.useEvent compatibility shim: The updates references that the stable useEvent points to before the possibility of event handlers or effects using stale references. It is pointed out that this is not a complete solution, though, because other useLayoutEffect calls could still reference stale referencesuseSyncExternalStore: The code comment above the useLayoutEffect usage explicitly mentions it needs to saving something for a check that happens in useEffect. I believe this usage of useLayoutEffect is indicative of the need for a new injection point in the React update process, which is being addressed via things like useSyncExternalStore and useEvent. I believe such usage will fade away as React develops appropriate abstractions but it's interesting to think back on how emergent practices in the community get turned into new features.