If you use server rendering, keep in mind that neither useLayoutEffect nor useEffect can run until the JavaScript is downloaded.
You might see a warning if you try to useLayoutEffect on the server. Here's two common ways to fix it.
If this effect isn't important for first render (i.e. if the UI still looks valid before it runs), then useEffect instead.
function MyComponent() {
useEffect(() => {
// ...
});
}Like useLayoutEffect, it won't run on the server, but it also won't warn.
If UI looks broken with useEffect but gets fixed by useLayoutEffect, it means that this component doesn't look right until the effect runs. However, that means the server-rendered HTML version of it won't look right until JavaScript loads anyway. So server-rendering it brings no benefit and shows a confusing UI.
To fix this, you can delay showing that component until after the client side JS loads and hydrates the component. To exclude a Child that needs layout effects from the server-rendered HTML, you can render it conditionally:
function Parent() {
const [showChild, setShowChild] = useState(false);
// Wait until after client-side hydration to show
useEffect(() => {
setShowChild(true);
}, []);
if (!showChild) {
// You can show some kind of placeholder UI here
return null;
}
return <Child {...props} />;
}
function Child(props) {
useLayoutEffect(() => {
// This is where your layout effect logic can be
});
}For example, this is handy for jQuery plugins which can be initialized later.
If you have some use case that isn't covered, please report a complete minimal code example here and we'll try to help.
@tenorok The reason is that
useLayoutEffectruns before the DOM is first rendered, whereasuseEffectruns after.With
useEffect, the first render on the client is going to be consistent with the server-side render. Because the server doesn't runuseEffect, and the client doesn't run it until after the first render.But
useLayoutEffectruns before the client's first render, and the server doesn't run it at all. So there might be a mismatch between the server's render and the client's first render. That's what the warning is telling us.(Edit: of course, to be technically precise, it's not the functions
useEffectanduseLayoutEffect, it's the callbacks passed to them, that run at different points in the component lifecycle).That's the reasoning, but this distinction is really splitting hairs. If
useEffectchanges the view (without waiting for some sort of promise to resolve) the update probably happens before the user can see the first render. And ifuseLayoutEffectwaits for a promise, the server's render will display in the meantime.So yeah, warning about one and not the other is highly questionable.