useEffect는 리액트 컴포넌트가 렌더링 될 때마다 특정 작업을 실행할 수 있도록 하는 Hook이다.
useEffect는 컴포넌트가 mount 됐을 때, update 됐을 때, unmount 됐을 때 특정 작업을 처리할 수 있다.
*클래스형 컴포넌트에서 사용할 수 있었던 생명주기(라이프사이클) 메서드를 함수형 컴포넌트에서도 사용할 수 있게 된 것이다.
첫번째 파라미터에는 함수, 두번째 파라미터에는 의존값이 들어있는 배열(deps)이 들어간다.
useEffect(() => {
console.log('컴포넌트가 화면에 나타남');
return () => {
console.log('컴포넌트가 화면에서 사라짐');
};
}, []);
컴포넌트 마운트 (처음 나타났을 때)
컴포넌트가 화면에 가장 처음 렌더링 될 때 한 번만 실행하고 싶을 때는 deps 위치에 빈 배열을 넣는다.
useEffect(() => {
console.log('마운트 될 때 실행)');
}, []);
만약 배열을 생략한다면 리렌더링 될 때마다 실행된다.
useEffect(() => {
console.log('렌더링 될 때 마다 실행');
});
컴포넌트 업데이트 (특정 props, state가 바뀔 때)
특정값이 업데이트 될 때 실행하고 싶을 때는 deps 위치의 배열 안에 검사하고 싶은 값을 넣어준다.
업데이트 될 때만 실행하는 것이 아니라 마운트 될 때도 실행된다.
useEffect(() => {
console.log(user);
console.log('업데이트 될 때 마다 실행');
}, [user]);
+따라서 업데이트 될 때만 특정 함수를 실행하고 싶다면 아래와 같은 꼼수를 사용하면 좋다.
// mounted의 current 값은 false 로 지정
const mounted = useRef(false);
useEffect(() => {
if(!mounted.current){
mounted.current = true;
} else {
// 원하는 코드 실행
}
}, [바뀌는 값]);
컴포넌트가 마운트 될 때는 if문에서 아무것도 실행하지 않고 mounted 값만 바꿔주고,
else에서 배열 안에 있는 값이 바뀌면, 원하는 코드를 실행할 수 있다.
컴포넌트 언마운트 (사라질때) / 업데이트 되기 직전
cleanup
함수 반환 (return 뒤에 나오는 함수이며 useEffect에 대한 뒷정리 함수라고 한다.)cleanup
함수를 실행하고 싶을 때 👉 두 번째 파라미터로 빈 배열을 넣는다.cleanup
함수를 실행하고 싶을 때 👉 deps 배열 안에 검사하고 싶은 값을 넣어준다.useEffect(() => {
console.log('effect'); // (2) 값이 업데이트 되면 바뀜.
console.log(name);
return () => {
console.log('cleanup'); // (1) 업데이트 직전에 호출되는 함수 (cleanup)
console.log(name);
}
}, [])
👉 useEffect 안에서 props
로 받아온 값을 참조하거나 useState로 관리하고 있는 값을 참조하고 있는 경우에는 deps
에 넣어주어야 한다. deps
에 넣지 않으면 useEffect에 등록한 함수가 실행될 때 최신 props
, 상태를 가리키지 않게된다.
deps
에 빈 배열을 넣었을 때는 처음 나타날 때인 마운트 될 때에만 첫번째 파라미터로 등록한 함수가 호출이 된다.
useEffect(() => {
console.log('컴포넌트가 화면에 나타남');
}, []);
이런식으로 컴포넌트가 3개 존재하는 경우 마운트 되면서 콘솔창에 '컴포넌트가 화면에 나타남' 이 3번 나타난다.
하지만 삭제(update)가 일어날 때는 호출되지 않는다.
deps
에 특정값이 존재할 때에는 처음 나타날 때(mount)와 값이 변경될 때마다(update), 언마운트 될 때, 값이 바뀌기 직전에 모두 useEffect에 등록한 함수가 호출된다.
그리고 해당 특정값이 바뀌기 직전에는 cleanup
함수가 반환된다.
useEffect(() => {
console.log(user);
}, [user]);
deps
위치에 파라미터를 생략하여 아예 없는 경우 컴포넌트가 리렌더링 될 때마다 useEffect 의 함수가 호출된다. (=모든 컴포넌트가 리렌더링 된다.)
이는 리액트 컴포넌트에서는 부모 컴포넌트가 리렌더링되면 자식 컴포넌트도 리렌더링 되기 때문이다.
useEffect(() => {
console.log(user);
});
매번 리렌더링 될 때 마다 업데이트가 되지 않은 것 까지 리렌더링 되다보니, 실제 DOM에 변화가 반영되는 것은 바뀐 내용이 있는 컴포넌트에만 해당하지만 Virtual DOM에서는 모든 것을 다 렌더링 하고 있다.
때문에 항목들의 수가 많아지게 된다면 성능이 느려질 수 있는 가능성이 있다.
따라서 Virtual DOM에 렌더링 되는 것도 최소화 해주는 것이 좋다.
이것을 컴포넌트 리렌더링 성능 최적화 라고 한다.
실행 시점: 업데이트 직전, 언마우트 전
useEffect 함수에서 return으로 함수를 반환하면 cleanup
함수가 반환된다.
useEffect 의 뒷정리를 담당하는 함수로, 업데이트 직전에 cleanup
함수가 반환된다.
deps
가 비어있는 경우 언마운트 시(컴포넌트가 사라질 때) cleanup
함수가 반환된다.
useEffect(() => {
console.log('user 값이 설정됨'); // (2) 값이 업데이트 되면 바뀜.
console.log(user);
return () => {
console.log('user 값이 바뀌기 전'); // (1) 업데이트 직전에 호출되는 함수 (cleanup)
console.log(user);
}
}, [user])
마운트 시 하는 작업
setInterval
을 통한 반복작업 혹은 setTimeout
을 통한 작업 예약언마운트 시 하는 작업
setInterval
, setTimeout
을 사용하여 등록한 작업을 clear하기 (clearInterval, clearTimeout)출처