At first glance, the useLayoutEffect
and useEffect
hooks look the same because they have a very similar function signature. There is, however, a subtle but important difference between them: the timing of when they get executed.
While useEffect
runs after the DOM paints to avoid blocking the page load, useLayoutEffect
runs before the DOM paints, which can help avoid issues with positioning or styling. Generally speaking, you want to use the useLayoutEffect
instead of useEffect
when you are interacting with the DOM directly.
Like useEffect
, useLayoutEffect
takes two arguments: a function and an optional dependency array.
useLayoutEffect(() => {
// Runs every time the component renders
}, [])
useLayoutEffect(() => {
// Runs only on initial render
}, []) // Optional second argument: dependency array
useLayoutEffect(() => {
// Runs only when 'apiData' changes
}, [apiData])
Ryan Harris: [0:00] Let's add an effect hook here, useEffect. We'll say const greenModal = document.querySelector. The className is " .Modal--lime". We'll say greenModal.style.transform = "translateX(-50%)". Then, we'll say greenModal.style.left. It's going to be 50% because these are absolutely positioned. greenModal.style.top = "". Now, if we say this, you'll notice that our green modal has moved to the top of the screen.
[0:54] If we come over here and refresh, you can see that this modal is blinking a little bit, because it's actually being positioned after the DOM paints, so we're getting a little flash of unwanted content.
[1:05] To prevent that, we would use the useLayoutEffect hook because it runs before the DOM paints. If we add a useLayoutEffect hook here, and we say const purpleModal = document.querySelector, we'll do the same thing, it's going to be " .Modal--purple". We're going to say purpleModal.style.transform = "translateX (-50%)", purpleModal.style.left = "50%" as well, and purpleModal.style.bottom = "".
[1:55] If we refresh the page, you can see that the green modal is flashing because it's being repositioned after the DOM paints. The purple modal, on the other hand, is staying in the same place because the styles were applied before the DOM painted.
[2:09] In summary, useEffect and useLayoutEffect have the same function signatures in taking a function, as well as an optional dependency array. The difference is that they run at different times. useLayoutEffect runs before painting, whereas useEffect happens after the DOM paints.
Heads up, I think your first useLayoutEffect hook in the above code block should omit the dependency array
[]
in order to be loaded on every render.