리액트 컴포넌트에는 라이프사이클(생명주기)이 존재한다. 라이프사이클은 컴포넌트가 처음 생성되는 단계인 Mount, 컴포넌트 내부가 업데이트되는 상태인 Update, 컴포넌트가 사라지는 단계인 Unmount로 구분된다.
(출처: https://projects.wojtekmaj.pl/react-lifecycle-methods-diagram/)
(출처: https://wavez.github.io/react-hooks-lifecycle/)
리액트 16.8 버전부터 hooks가 생긴 이후로, 함수형 컴포넌트에서 useEffect hooks를 사용하여, 클래스형 컴포넌트에 존재하던 여러가지 생명주기 메소드들을 사용할 수 있다.
(출처: https://ko.reactjs.org/docs/hooks-effect.html)
리액트 공식문서에도 팁으로 나와있듯이, useEffect를 사용하여 componentDidMount, componentDidUpdate, componentWillUnmount를 대체하여 사용할 수 있다.
useEffect(() => {
console.log("최초렌더 & 리렌더");
});
위 코드와 같이 useEffect 괄호 안에 선언된 함수가 실행된다. 컴포넌트가 렌더되고, DOM에 반영 된 후에 실행되는 함수를 작성할 수 있다.
useEffect(() => {
console.log("최초렌더");
}, []);
위 코드에서 처럼 useEffect 괄호안에 쉼표 뒤에 빈배열을 넣으면 컴포넌트가 최초로 렌더됐을 때(mount 됐을 때) 실행 되는 함수를 작성할 수 있다.
useEffect(() => {
console.log("최초렌더 & num 변화");
}, [num]);
num이라는 이름의 state 또는 props가 있다고 하자. 쉼표 뒤에 있는 배열에 num을 추가하면 컴포넌트가 mount되거나, num의 값이 업데이트 될 때 마다 실행시킬 함수를 작성 할 수 있다.
useEffect(() => {
return () => console.log(`언마운트`);
}, []);
2)에서와 같은 방식으로 useEffect괄호 내부를 작성하는데, 여기서는 함수내부에서 return을 활용하여 unmount 됐을 때 실행시킬 함수를 작성하면 된다.
function App() {
const [num, setNumber] = useState(0);
const [showChild, setShowChild] = useState(true);
const handleUpClick = () => setNumber((prev) => prev + 1);
const handleToggleClick = () => setShowChild((prev) => !prev);
return (
<>
<div>
<h2>LifeCycle</h2>
<button onClick={handleToggleClick}>Toggle</button>
{showChild ? (
<>
<Children num={num} />
<button onClick={handleUpClick}>UP</button>
</>
) : null}
</div>
</>
);
}
export default App;
function Children({ num }: { num: number }) {
const ref = useRef(num);
useEffect(() => {
console.log("최초렌더 & 리렌더");
});
useEffect(() => {
console.log("최초렌더");
}, []);
useEffect(() => {
console.log("최초렌더 & 숫자 변화");
}, [num]);
useEffect(() => {
return () => console.log(`언마운트`);
}, []);
return (
<>
{console.log("리턴")}
<div>
<h4>{num}</h4>
</div>
</>
);
}
export default Children;