리액트에서 effect를 사용하면 언제 코드가 실행될지를 결정할 수 있다.
컴포넌트에서 state를 변경하면 그 컴포넌트 안 '모든' 코드들을 항상 다시 실행된다. 그러나 어떤 경우에는 특정 코드들이 딱 한 번만 실행되어야 할 경우도 있을 것이고 특정한 부분이 변화했을 때만 실행되어야 할 경우도 있을 것이다.
이럴 경우에 쓸 수 있는 함수가 useEffect 이다.
useEffect는 두 개의 인자를 받는데 첫 번째 인자는 실행하려는 코드이고 두 번째 인자는 react.js가 지켜보아야 하는 것들, 즉 dependency이다.
function App() {
const [counter, setValue] = useState(0);
const [keyword, setKeyword] = useState("");
const onClick = () => setValue((prev) => prev + 1);
const onChange = (event) => setKeyword(event.target.value);
useEffect(() => {
console.log("I run only once.");
}, []);
useEffect(() => {
console.log("I run when 'keyword' changes. ");
}, [keyword]);
useEffect(() => {
console.log("I run when 'counter' changes. ");
}, [counter]);
return (
<div>
<input
value={keyword}
onChange={onChange}
type="text"
placeholder="Search here"
/>
<h1>{counter}</h1>
<button onClick={onClick}>click me</button>
</div>
);
}
위 예시의 첫 번재 useEffect 처럼 dependency에 빈 배열을 쓰면 react.js가 지켜볼 게 없으니 컴포넌트가 처음 생성될 때 호출하고 다시는 호출하지 않는다.
두 번째 useEffect는 'keyword'라는 state가 변화할 때만 코드들을 실행시킨다는 뜻이다. 마찬가지로 세 번째는 'counter'의 state가 변화할 때만 코드를 실행시킨다는 뜻이다.
dependency에 [keyword, counter]과 같이 여러 개를 쓸 수 있다. 이는 둘 중 하나라도 변화가 일어나면 코드를 실행시킬 수 있따는 뜻이다.
Cleanup function
컴포넌트가 파괴될 때에도 코드를 실행시킬 수 있다. 파괴될 때 실행할 함수를 만들면 되는데 useEffect 함수가 새로운 함수를 return 해야 한다.
function Hello() {
useEffect(() => {
console.log("created :)");
return () => console.log("destroyed :(");
}, []);
return <h1>Hello</h1>;
}
function App() {
const [showing, setShowing] = useState(false);
const onClick = () => setShowing((prev) => !prev);
return (
<div>
{showing ? <Hello /> : null}
<button onClick={onClick}>{showing ? "Hide" : "Show"}</button>
</div>
);
}
컴포넌트가 파괴될 때 react.js는 useEffect안 함수가 return한 함수를 실행한다.
리렌더링으로 useEffect 함수가 실행되고 클린업하면서 이전에 있던 이펙트인 console.log("created :)")가 삭제되고 새로운 이펙트 함수인 return 함수가 실행된다.
이처럼 useEffect를 쓰면 코드를 언제 실행할지를 결정할 수 있고 컴포넌트가 파괴될 때에도 코드를 실행시킬 수 있다.