Difference between useEffect and useLayoutEffect

Jul 01, 2023#react#comparison

The useEffect and useLayoutEffect hooks are both used to perform side effects in React function components. Side effects are any operations that affect something outside the scope of the component, such as fetching data, manipulating the DOM, setting timers, etc.

The main difference between useEffect and useLayoutEffect is the timing of their execution. The useEffect hook runs asynchronously after the component has rendered and the browser has painted the screen. The useLayoutEffect hook runs synchronously after the component has rendered but before the browser has painted the screen.

This difference can have significant implications for the performance and user experience of your app. Here are some examples of when to use useEffect or useLayoutEffect:

  • If your side effect does not depend on or affect the DOM layout, such as fetching data from an API, logging something to the console, or updating a state variable, you can use useEffect. This way, you avoid blocking the browser from painting the screen and causing layout thrashing. For example:
useEffect(() => {
  // fetch some data from an API
  fetch("/api/users")
    .then((res) => res.json())
    .then((data) => setUser(data));
}, []);
  • If your side effect depends on or affects the DOM layout, such as measuring the size or position of an element, changing a CSS property, or animating a transition, you should use useLayoutEffect. This way, you ensure that your side effect runs before the browser paints the screen and avoids any visual inconsistency or flickering. For example:
useLayoutEffect(() => {
  // measure the height of an element
  const height = ref.current.offsetHeight;
  // set the height as a CSS variable
  document.documentElement.style.setProperty("--height", `${height}px`);
}, []);
  • If your side effect is triggered by a user interaction, such as a click or a keypress, you should use useEffect if possible. This way, you avoid delaying the response time of the interaction and improve the perceived performance of your app. However, if your side effect needs to run synchronously to prevent visual glitches, you can use useLayoutEffect. For example:
useEffect(() => {
  // toggle a modal when a button is clicked
  if (showModal) {
    document.body.classList.add("modal-open");
  } else {
    document.body.classList.remove("modal-open");
  }
}, [showModal]);

It’s important to note that using useLayoutEffect can potentially cause performance issues because it can block the browser’s rendering, resulting in slower updates. In most cases, useEffect is the recommended choice because it doesn’t block rendering and provides a smoother user experience. Only use useLayoutEffect when you absolutely need to perform DOM measurements or updates that require immediate effect.

react hook lifecycle