React Grimoire
  • โ‰๏ธIntroduction
  • ๐Ÿง‘โ€๐ŸŽ“๐Ÿง‘๐ŸŽ“ React Fundamentals
    • The Basic javascript "Hello world"
    • Basic view on React core API's
    • JSX
    • React Props and styling
    • Components
    • Handling Events With React
    • Form
    • Array and Lists
    • Class Component State
    • Class Component Life Cycle
    • PropTypes
  • ๐ŸชReact Hooks
    • Intro to hooks
    • useState
    • useEffect
    • useRef
    • useContext
    • useMemo
    • useCallback
    • useReducer
    • useLayoutEffect
    • useImperativeHandle
    • Hook flow
    • Custom hooks
      • useDebugValue
    • React 18 hooks
  • ๐Ÿ““React Guidelines
    • React Components Composition Guidelines
    • React hooks guidelines
    • The use of Memoization
    • Lifting State Up
  • ๐Ÿ”ญConcepts
    • Advanced Patterns
      • Compound Components Pattern
      • Control Props Pattern
      • Props Getters Pattern
      • Custom hook pattern
      • Context Module
      • State Reducer
    • React Under the hood
      • ๐ŸWhat is "Rendering"?
      • ๐ŸReact Lifecycle
      • ๐ŸReconciliation & Virtual DOM in React
      • ๐ŸFiber
    • โฐConcepts to always have in mind
  • ๐ŸงฉReact ecosystem
    • Forms Tools
      • React Hook Form VS Formik
    • TypeScript
      • ๐ŸConditional React props with TypeScript
    • ๐ŸBuild tool choice for MVP projects
    • A CSS methodology comparison
      • ๐ŸPost CSS processor :Sass
      • ๐ŸCSS in js :Styled-components
      • ๐ŸUtility Classes: Tailwind
  • โ‰๏ธTesting
    • In Progress
  • ๐ŸŽญPerformance
    • in Progress
  • ๐Ÿš€Deployment
    • In Progress
  • ๐Ÿ–ผ๏ธDesign system
    • ๐ŸWhat's a design system anyway ?โ€‹?
  • ๐Ÿ”—Us-full links
    • Typescript and React basic tutorial
    • React-philosophies
    • React new doc
Powered by GitBook
On this page
  • Timing of an effect
  • useEffect vs useLayoutEffect
  • Why Use useLayoutEffect?
  • You Probably Don't Need useLayoutEffect
  • References and articles :

Was this helpful?

Edit on GitHub
  1. React Hooks

useLayoutEffect

PrevioususeReducerNextuseImperativeHandle

Last updated 3 years ago

Was this helpful?

Your useLayoutEffect callback/effects will be fired synchronously after all DOM mutations, i.e., before the browser has a chance to paint.

This can be useful if you need to make DOM measurements (like getting the scroll position or other styles for an element) and then make DOM mutations or trigger a synchronous re-render by updating state.

It is recommended that you use useEffect when possible to avoid blocking visual updates. However, there are legitimate use cases for useLayoutEffect, e.g., to read layout from the DOM and synchronously re-render.

If you are migrating code from a class component, useLayoutEffect fires in the same phase as componentDidMount and componentDidUpdate, but start with useEffect first, and only try useLayoutEffect if that causes a problem. Donโ€™t block visual updates except when youโ€™re absolutely sure you need to.

Itโ€™s also worth mentioning that with server-side rendering, neither useEffect nor useLayoutEffect are run until JavaScript is downloaded on the client.

Youโ€™ll get a warning with server-rendered components containing useLayoutEffect. To resolve this, you can either move the code to useEffect, i.e., to be fired after first render (and paint), or delay showing the component until after the client renders.

useLayoutEffect(() => {
//do something
}, [arrayDependency])

It looks exactly like useEffect but different use-cases. Here is the syntax for it

const component =() => {
    const [randomNumber, setRandomNumber] = useState(0)
    const [effectLogs, setEffectLogs] = useState([])
  
    useLayoutEffect(
      () => {
        setEffectLogs(prevEffectLogs => [...prevEffectLogs, 'effect fn has been invoked'])
      },
      [randomNumber]
    )
  
    return (
      <div>
        <h1>{randomNumber}</h1>
        <button
          onClick={() => {
            setRandomNumber(Math.random())
          }}
        >
          Generate random number!
        </button>
        <div>
          {effectLogs.map((effect, index) => (
            <div key={index}>{'๐Ÿ”'.repeat(index) + effect}</div>
          ))}
        </div>
      </div>
    )
  }

Timing of an effect

Thereโ€™s a very big difference between when the useEffect callback is invoked and when class methods such as componentDidMount and componentDidUpdate are invoked.

The effect callback is invoked after the browser layout and painting are carried out. This makes it suitable for many common side effects, such as setting up subscriptions and event handlers since most of these shouldnโ€™t block the browser from updating the screen.

This is the case for useEffect, but this behavior is not always ideal.

What if you wanted a side effect to be visible to the user before the browserโ€™s next paint? Sometimes, this is important to prevent visual inconsistencies in the UI,.

For such cases, React provides another Hook called useLayoutEffect. It has the same signature as useEffect; the only difference is in when itโ€™s fired, i.e., when the callback function is invoked.

N.B., although useEffect is deferred until the browser has painted, it is still guaranteed to be fired before any re-renders. This is important.

React will always flush a previous renderโ€™s effect before starting a new update.

useEffect vs useLayoutEffect

useEffect (Component > State Changes > Component Renders > Rendered Component is Printed on Screen > useEffect runs)

useEffect will run after React renders your component and ensures that your effect callback does not block browser painting.

useLayoutEffect (Component > State Changes > Component Renders > useLayoutEffect runs > Rendered Component is Printed on Screen)

useLayoutEffect runs synchronously immediately after React has performed all DOM mutations.

Why Use useLayoutEffect?

So if useLayoutEffect will delay the painting of a component why would we want to use it. The biggest reason for using useLayoutEffect is when the code being run directly modifies the DOM in a way that is observable to the user.

For example, if I needed to change the background color of a DOM element as a side effect it would be best to use useLayoutEffect since we are directly modifying the DOM and the changes are observable to the user. If we were to use useEffect we could run into an issue where the DOM is painted before the useEffect code is run. This would cause the DOM element to be the wrong color at first and then change to the right color due to the useEffect code.

You Probably Don't Need useLayoutEffect

As you can see from the previous example, use cases for useLayoutEffect are pretty niche. In general it is best to always use useEffect and only switch to useLayoutEffect when you actually run into an issue with useEffect causing flickers in your DOM or incorrect results.

References and articles :

๐Ÿช
Hooks API Reference โ€“ React
React useLayoutEffect vs. useEffect with examples - LogRocket BlogLogRocket Blog
Logo
useEffect vs useLayoutEffectkentcdodds
An illustration of the effect callback
useEffect is fired before any new re-renders
Logo
Logo