컴포넌트의 렌더링 직후에 동기적으로 실행되는 효과(Effect)를 생성할 때 사용하는 리액트 훅
비동기적으로 실행되며, 컴포넌트의 렌더링이 완료된 후 실행된다. 즉, 렌더링 작업 후에 실행되기 때문에 렌더링이 끝난 화면을 사용자에게 보여준 다음 효과를 실행한다.
useLayoutEffect
동기적으로 실행되며, 컴포넌트의 렌더링 직후에 실행된다. 즉, 렌더링 작업이 완료되기 전에 실행되므로 렌더링 작업을 차단할 수 있다.
비동기적으로 실행되기 때문에 렌더링 작업을 차단하지 않는다. 사용자에게 화면을 먼저 보여주고, 효과는 나중에 실행된다.
동기적으로 실행되므로 렌더링 작업을 차단할 수 있다. 따라서 주의해서 사용해야 하며, 렌더링 작업에 대한 지연을 발생시킬 수 있으므로 성능에 영향을 미칠 수 있다.
import { useEffect, useState } from "react";
function Example() {
const [name, setName] = useState("");
const [job, setJob] = useState("")
useEffect(() => {
setName("민택");
setJob("개발자")
}, []);
return (
<>
<div className="App">{`내 이름은 ${name}이고, 직업은 ${job} 입니다.`}</div>
</>
);
}
export default Example;
useEffect
를 사용한 코드는 다음과 같은 순서로 실행된다.<div>내 이름은 이고, 직업은 입니다.</div>
을 페인트
이펙트 내부의 setName
, setJob
호출
재렌더링 실행 => <div>내 이름은 민택이고, 직업은 개발자 입니다.</div>
import { useLayoutEffect, useState } from "react";
function Example() {
const [name, setName] = useState("");
const [job, setJob] = useState("")
useLayoutEffect(() => {
setName("민택");
setJob("개발자")
}, []);
return (
<>
<div className="App">{`내 이름은 ${name}이고, 직업은 ${job} 입니다.`}</div>
</>
);
}
export default Example;
useLayoutEffect
는 브라우저가 화면에 DOM을 그리기 전에 이펙트를 수행하는데, 따라서 위 코드의 실행 순서는 아래와 같다.setName
, setJob
호출<div>내 이름은 민택이고, 직업은 개발자 입니다.</div>
를 페인트useLayoutEffect 는 동기적으로 실행되고 내부의 코드가 모두 실행된 후 페인팅 작업을 거친다. 따라서 로직이 복잡할 경우 사용자가 레이아웃을 보는데까지 시간이 오래걸린다는 단점이 있어, 기본적으로는 항상 useEffect 만을 사용하는 것을 권장한다.
위 3가지 작업 등은 항상 useEffect를 사용하되,
import { useLayoutEffect, useState } from "react";
function Test(){
const [value, setValue] = useState(0);
useLayoutEffect(() => {
if (value === 0) {
setValue(10 + Math.random() * 200);
}
}, [value]);
console.log('render', value);
return (
<button onClick={() => setValue(0)}>
value: {value}
</button>
);
}
화면이 깜빡거리는 상황일 때, 예를들어 위와같이 state
가 존재하며, 해당 state
이 조건에 따라 첫 페인팅 시 다르게 렌더링 되어야 할 때는 useEffect
사용 시 처음에 0이 보여지고 이후에 리렌더링 되며 화면이 깜빡거려지기 때문에 useLayoutEffect
를 사용하는 것이 바람직하다.