useEffect는 리액트 컴포넌트가 렌더링될 때마다 특정 작업을 수행하도록 설정할 수 있는 hook입니다.
class의 componentDidMount와 componentDidUpdate, componentWillUnmount를 합쳐놓은 것과 같습니다. 이 api들은 대체로 side effect를 처리하는 애들이었죠.
class Example extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 0
};
}
componentDidMount() {
document.title = `You clicked ${this.state.count} times`;
}
componentDidUpdate() {
document.title = `You clicked ${this.state.count} times`;
}
render() {
return (
<div>
<p>You clicked {this.state.count} times</p>
<button onClick={() => this.setState({ count: this.state.count + 1 })}>
Click me
</button>
</div>
);
}
}
위의 예제는 side effect를 처리하기 위해 componentDidMount와 coponentDidUpdate에서 처리를 해두었습니다. 이들은 dom이 생성된 이후에 동작해야하기 때문에 이 lifecycle api method에 넣어야 하며, 매 렌더링 시마다 동작하길 원하기 때문에 2군데의 lifecycle api method에 같은 명령어를 중복으로 넣어야 합니다.
코드가 중복되는 것이 별로지만 class 컴포넌트에서는 어쩔 수 없었습니다.
훅에서는 이를 어떻게 단일화했는지 살펴봅시다.
import React, { useState, useEffect } from 'react';
function Example() {
const [count, setCount] = useState(0);
useEffect(() => {
document.title = `You clicked ${count} times`;
});
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
useEffect는 렌더링될 때마다 실행되므로 렌더링시기에 어떤 작업을 하고자 할 때 유용합니다.
렌더링이 되는 경우는 마운트와 업데이트 두 가지의 경우입니다.
useEffect의 첫번째 파라미터로 넘기는 함수에서는 렌더링 된 후에 실행되는 코드들이며
첫번째 파라미터 안에서 반환하는 함수 안에 작성된 코드는 현재 컴포넌트와 값이 사라지기 전에 실행되는 코드들입니다.
리턴함수를 여기서는 cleanup함수라고 하는데, cleanup함수가 호출될 때는 업데이트되기 직전의 값을 보여줍니다.
이를 더 세분화하여 마운트와 업데이트로 나누는 기준은 두번째 파라미터 값의 형태에 달려있습니다.
빈 배열을 전달하면 마운트 관련 렌더링에서만 동작하고, 검사하고 싶은 값을 넣은 배열을 넣으면 해당 값이 업데이트 될때만 호출되며,
두번째 파라미터에 아무 것도 전달하지 않으면 마운트/언마운트, 업데이트 때마다(매순간 렌더링 순간마다) 호출됩니다.