useEffect Hook을 사용하면 구성 요소에서 부작용을 수행할 수 있다.
부작용의 몇 가지 예는 데이터 가져오기, DOM 직접 업데이트 및 타이머이다.
useEffect는 두 개의 인수를 허용한다.
useEffect(function, dependency)
// setTimeout() 초기 렌더링 후 1초를 계산하는데 사용
import { useState, useEffect } from "react";
import ReactDOM from "react-dom/client";
function Timer() {
const [count, setCount] = useState(0);
useEffect(() => {
setTimeout(() => {
setCount((count) => count + 1);
}, 1000);
});
return <h1>I've rendered {count} times!</h1>;
}
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<Timer />);
useEffect는 모든 렌더링에서 실행된다. 즉, 개수가 변경되면 렌더링이 발생하고 다른 효과가 트리거된다.
이때, 시기를 제어하는 몇 가지 방법이 있다.
배열을 허용하는 두 번째 매개변수[deps]를 항상 포함해야한다. useEffect는 선택적으로 이 배열에 종속성을 전달할 수 있다.
1. 빈 배열
- 처음 시작할 때 한번만 렌더링이 일어남
useEffect(() => {
...
}, []);
2. 소품 또는 상태 값
- 처음 시작할 때 한번만 렌더링이 일어남
- deps가 변화할 때마다 렌더링이 일어남
useEffect(() => {
...
}, [prop, state]);
일부 효과는 메모리 누수를 줄이기 위해 정리가 필요하다.
더 이상 필요하지 않은 시간 초과, 구독, 이벤트 리스너 및 기타 효과는 삭제해야 한다.
useEffect Hook의 끝에 return 함수를 포함하여 이를 수행한다.
retur을 함으로서, unmount 시킬 수 있다.
import { useState, useEffect } from "react";
import ReactDOM from "react-dom/client";
function Timer() {
const [count, setCount] = useState(0);
useEffect(() => {
let timer = setTimeout(() => {
setCount((count) => count + 1);
}, 1000);
return () => clearTimeout(timer)
}, []);
return <h1>I've rendered {count} times!</h1>;
}
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<Timer />);
훅이 나오기 전 리액트의 생명주기는 클래스형 컴포넌트의 생명주기 메소드를 사용하였다.
useEffect(() => {
consloe.log('componentDidmount')
}, []);
useEffect(() => {
console.log('componentDidUpdate')
})
useEffect(() => {
console.log('componentDidUpdate')
}, [state, props])
useEffect(() => {
console.log('componentDidmount');
return () => {
console.log('componentWillUnmount');
}
}, [])
useEffect의 의존성 배열에 빈 값 전달
useEffect에 return 함수 사용(clean-up 함수)
deps를 사용하지 않으면 계속 사용되고 deps에 빈 값을 전달하면 끝날 때 단 한번 실행한다.