useEffect 는 리액트 컴포넌트가 렌더링 될 때마다 특정 작업을 수행하도록 설정 할 수 있는 Hooks 이다. 클래스형 컴포넌트의 componentDidMount 와 componentDidUpdate 를 합친 형태라 생각하면 이해가 쉽다.
아래 코드는 버튼을 올리면 카운트를 올리는 간단한 코드이다 한번 살펴보자
import { useRef, useState, useEffect } from "react";
import { useRouter } from "next/router";
export default function CounterPage() {
const router = useRouter();
const inputRef = useRef<HTMLInputElement>(null);
const [count, setCount] = useState(99);
// 1번 DidMount
// useEffect(() => {
// console.log("마운트됨");
// inputRef.current?.focus();
// }, []);
// componentDidUpdate() {
// console.log("수정되고 다시그려짐!!!");
// }
// 위의 useEffect와 대괄호 차이
// 2번 DidUpdate
useEffect(() => {
console.log("수정되고 다시그려짐!!!");
}, [count]); // count 변경시 실행을 의미
// [count, writer, title]); 이 될경우 셋중 하나만 바뀌어도 실행이됨
// componentWillUnmount() {
// console.log("컴포넌트 사라짐!!!");
// // 채팅방 나가기
// // api 요청!!!
// }
// 3번 Willunmount
// useEffect(() => {
// return () => {
// console.log("컴포넌트 사라짐!!!");
// };
// }, []);
// 4번 DidMount와 willUnmount를 합치기!!
useEffect(() => {
console.log("마운트됨");
inputRef.current?.focus();
return () => {
console.log("컴포넌트 사라짐!!!");
};
}, []);
// [] 는 의존성 배열(Dependency Array)라 하며 함수 실행여부를 의존한다. 비었을 경우 한번 실행한 후 끝
// 5번 useEffect의 잘못된 사용 예시() 1.추가 랜더링, 2.무한루프
// useEffect안에서 setState를 사용시 재 랜더링이 발생한다.
// 어쩔수 없을 경우가 아니라면 가능하면 빼주는게 좋다.
// 1. 추가랜더링
// useEffect(() => {
// setCount(10);
// }, []);
// 2. 무한루프
// useEffect(() => {
// setCount((prev) => prev + 1);
// }, [count]);
const onClickCounter = () => {
setCount((prev) => prev + 1);
};
const onClickMove = () => {
router.push("/");
};
return (
// div의 범위가 현재 컴포넌트
<div>
{/* 객체 안의 정보를 가져오기에 {} 를 한다. */}
<input type="text" ref={inputRef} />
<div>현재카운트{count}</div>
<button onClick={onClickCounter}>카운트 올리기!!!</button>
<button onClick={onClickMove}>나가기!!!</button>
</div>
);
}
우선 const [count, setCount] = useState(99);
를 통해 state를 하나 만들어 초기값은 숫자로 주었다.
1번
1번 DidMount
useEffect(() => {
console.log("마운트됨");
inputRef.current?.focus();
}, []);
위 부분은 클래스형 컴포넌트의 DidMount라 보면된다.
화면이 랜더링됨과 동시에 작동하는 부분이다.
그런데 코드의 마지막 부분을 보면 [ ]가 들어있다.
[] 는 의존성 배열(Dependency Array)라 하며 함수 실행여부를 의존한다.
위 코드 처럼 [ ] 안쪽이 비었을 경우 한번 실행한 후 다시 다시 실행되지 않으며,
위 코드는 결국 화면 랜더링 최초1회한정으로 적용이되는 함수라는 소리이다.
2번
//2번 DidUpdate
useEffect(() => {
console.log("수정되고 다시그려짐!!!");
}, [count]); // count 변경시 실행을 의미
// [count, writer, title]); 이 될경우 셋중 하나만 바뀌어도 실행이됨
위 부분은 클래스형 컴포넌트의 componentDidUpdate() 라고 생각하면 된다.
Update라는 의미 그대로 변경시 효과를 나타내며 위에서 설명한 의존성배열 안에
State값인 count
를 넣어서 count
가 setState
에 의해 변경 될 때 마다 콘솔에 로그를 띄워준다.
3번
3번 Willunmount
useEffect(() => {
return () => {
console.log("컴포넌트 사라짐!!!");
};
}, []);
이 부분은 willunmount에 속한다. 마운트가 해제되는 시점으로
의존성 배열 부분이 비어있으므로 한번 만실행되며
return
안에 console.log
가 들어가 있는데 이는 특정한 이벤트가 발동 될 경우 이벤트가 일어난단 소리이다.
위의 경우에는 마운트가 종료되는 시점에 콘솔이 나올것이다.
4번
4번 DidMount와 willUnmount를 합치기!!
useEffect(() => {
console.log("마운트됨");
inputRef.current?.focus();
return () => {
console.log("컴포넌트 사라짐!!!");
};
}, []);
이부분은 DidMount와 willUnmount가 합쳐진 부분이라 생각하면 된다.
최초1회 한해서 console.log("마운트됨");
가 실행되며 나중에 특정이벤트(해당코드에선 마운트 해제)
가 될경우 return문이 발동되는 것이다.
일반적인 진행은 1~3번이고 4번은 1,3번을 합쳐서 응용한 느낌이라 생각하면된다.
상황에 따라 return문을 활용해 랜더를 원하는 곳에 해주면 된다.
5번
5번 useEffect의 잘못된 사용 예시() 1.추가 랜더링, 2.무한루프
useEffect안에서 setState를 사용시 재 랜더링이 발생한다.
어쩔수 없을 경우가 아니라면 가능하면 빼주는게 좋다.
// 1. 추가랜더링
// useEffect(() => {
// setCount(10);
// }, []);
// 2. 무한루프
// useEffect(() => {
// setCount((prev) => prev + 1);
// }, [count]);
5번의 경우는 useEffect
안에 setState
를 넣은 경우이다.
useEffect
는 자체적으로도 랜더를 시켜주는 Hooks인데 안쪽에서
setState
가 동작할 경우 리랜더링이 되며 서버에 부하를 준다.
5-2번 같은경우엔 State
값인count
가 무한루프되는 현상이 발생하기도 한다.