useEffect, useLayoutEffect
useEffect / useLayoutEffect

 

useEffect()


리액트의 useEffect()는 해당 스코프의 컴포넌트가 render와 paint 된 후 호출되는 리액트 라이프사이클 훅이다. 비동기적으로 실행되고 로직에 DOM에 영향을 주는 코드가 있을 경우 사용자는 화면의 깜빡임을 확인할 수 있다.

 

useLayoutEffect()


useLayoutEffect()는 컴포넌트가 render가 되고 호출된다. paint 전에 호출 된다는 점이 useEffect()와 다른데,. 만약 DOM에 영향을 주는 로직(setState)이 있을 경우 화면에 그려지기 전 실행되므로 사용자는 깜빡임을 경험할 수 없다.

 

주의할 점은 useLayoutEffect는 동기적으로 실행되므로 로직이 처리되는 시간 동안 사용자는 빈화면을 볼 수밖에 없으므로 목적에 맞게 잘 사용해야한다.

 

Next.js 개발 환경에서의 경고


SSR 환경에서는 자바스크립트가 모두 다운로드될 때까지 useEffect와 useLayoutEffect는 실행되지 않는다. 그 말은 클라이언트 환경에서만 실행된다는 이야기고 Next.js에서 useLayoutEffect를 사용할 경우 서버에서 렌더링 되는 과정에서 터미널에 경고 메시지가 출력된다.

 

Warning: useLayoutEffect does nothing on the server, because its effect cannot be encoded into the server renderer's output format. This will lead to a mismatch between the initial, non-hydrated UI and the intended UI. To avoid this, useLayoutEffect should only be used in components that render exclusively on the client. See https://reactjs.org/link/uselayouteffect-ssr for common fixes.

 

useLayoutEffect는 paint 전 로직이 실행되므로 서버에서의 render 화면과 클라이언트의 render 화면이 다를 수 있다는 경고라는데, 목적에 맞게 useLayoutEffect를 사용한다해도 해당 경고 알림은 뜨게된다.

 

저도 useLayoutEffect() 에서 비동기 로직이 아닌 단순 계산식을 돌렸을 뿐이고 클라이언트에서 렌더링 하는데 전혀 영향을 미칠만한 코드도 아니였으므로 해당 오류가 낮설었습니다. 😰

 

해결방법

import { useState, useEffect, useLayoutEffect, useCallback } from 'react'

const useMultiEffect = typeof window !== 'undefined' ? useLayoutEffect : useEffect

 

SSR 개발 환경에서는 window 객체 여부로 서버와 클라이언트를 구분해 Vercel의 눈을 속이는 useMultiEffect를 선언해서 사용해 주면 됩니다.

 

해당 방법은 react-redux 에서도 사용하고 있다고 합니다. 👍

 

참고


 

useEffect와 useLayoutEffect의 차이

예전에 데이터에 따라 DOM 조작이 필요했었는데, 이때 화면의 깜빡임을 없애기 위해 useEffect 대신 useLayoutEffect를 사용했었다. 그러나 정확히 이 둘의 차이가 무엇인지 생각해보면, 대답할 수 없었

www.howdy-mj.me

 

What is useLayoutEffect Hook & how it compares to useEffect?

React Hooks were released a couple of years ago when React ecosystem introduced a new way to handle state and effects in a function-based component. Although there isn't any sudden plan to completely deprecate the class-based approach, however, web applica

javascript.works-hub.com

 

 

useLayoutEffect and SSR

How to get warning free usage of useLayoutEffect when server-side rendering

medium.com