이번 포스팅에서는 React.js 훅 중에 하나인 useEffect에 대해서 간단하게 알아볼 것이다.
useEffect 훅은 Side-Effect를 처리할 때 사용한다.
useEffect은 컴포넌트가 랜더링 된 이후에 실행이 된다.
import {useState, useEffect} from 'react';
useEffect를 사용하는 방법은 3가지가 있다.
첫 번째는 Dependency가 없는 형태이다.
useEffect(() => {});
이런 형태는 잘 사용하지 않는다. Dependency를 설정하지 않을 시 어떤 작은 변화라도 감지하여 useEffect가 작동하기 때문이다.
두 번째는 Dependency가 있는 형태이다.
useEffect(() => {}, []);
첫 번째 방법과는 다르게 대괄호가 포함된 걸 확인할 수 있다.
대괄호는 Dependency 라고 하는데 대괄호 안에 state를 넣어주면 리액트는 항상 해당하는 값이 변화하는지 쳐다보게 된다. 그리고 값이 바뀔 시 useEffect를 다시 실행한다.
만약 Dependency를 비어놨을 시 해당 useEffect는 최초로 랜더링 될 때만(Mount) 실행이 된다.
세 번째 방법은 Dependency 에 구독할 내용을 넣어주는 것이다.
useEffect(() => {}, [state]);
useEffect의 Dependency에 state를 추가해줌으로써 리액트에게 해당 상태를 계속 추적해달라고 요청해놨다.
그래서 React는 해당 상태를 계속 추적하며 만약 상태가 변화할 시 useEffect를 다시 실행하게 된다. (상태가 변화하면 랜더링이 되면서)
간단한 테스트를 위해 훅을 통해서 state를 생성한다.
import {useState, useEffect} from 'react';
export default function App() {
const [count, setCount] = useState(0);
const onClick = () => {
setCount((prev) => prev+1);
console.log(count);
};
useEffect(() => {
console.log("Side-Effect");
},[]);
return (
<div>
<span>{count}</span>
<button onClick={onClick}>count++</button>
</div>
)
}
작성된 코드를 설명해보면, 먼저 useState 훅을 통해서 state를 만들었다.
기본 값은 0이며 버튼을 클릭할 시 state가 하나씩 늘어나도록 Modifier (setCount)를 설정해놨다.
먼저 Dependency에 추적하는 값이 없을 때 어떻게 실행이 되는지 살펴보자.
컴포넌트가 마운트가 될 때 최초로 한번 useEffect가 발동했다.
이는 컴포넌트 생명주기 함수 중 componentDidMount
에 해당한다.
콘솔창에 side-Effect가 찍혀있는 걸 확인할 수 있다.
'count++' 버튼을 통해서 state를 변화시켜보자! (state가 변화할 시 리랜더링)
Count를 여러번 눌러서 state가 변화했지만 Side-Effect는 실행되지 않았다.
이유는 Dependency에 구독할 값을 설정하지 않았기 때문이다.
그렇다면 Dependency에 count를 넣고 해당 value를 추적해달라고 해보자!
import {useState, useEffect} from 'react';
export default function App() {
const [count, setCount] = useState(0);
const onClick = () => {
setCount((prev) => prev+1);
console.log(count);
};
useEffect(() => {
console.log("Side-Effect");
},[count]);
return (
<div>
<span>{count}</span>
<button onClick={onClick}>count++</button>
</div>
)
}
정말 간단하게 변한건 Dependency 밖에 없다.
처음 컴포넌트가 마운트 될 때 모습이다. 예상처럼 useEffect가 발동했다.
이는 컴포넌트 생명주기 중 componentDidUpdate
, getDerivedStateFromProps
에 해당한다.
그렇다면 count++ 버튼을 통해 state를 변화시켜보자.
count 버튼을 통해 state를 증가시킬때 마다 useEffect가 발동한다.
React가 count라는 값을 구독하고 있기 때문이다!
보통 useEffect는 컴포넌트가 마운트 될 때 딱 한번만 실행되었으면 하는 로직이나, 값이 변할때 마다 추적해야할 사항이 있을 때 사용한다.
예제를 한번 살펴보자.
useEffect(() => {
(async () => {
const response = await fetch("https://api.coinpaprika.com/v1/coins");
const json = await response.json();
setCoins(json.slice(0, 100));
})();
}, []);
위 예제에서는 비동기 로직을 이용해 최초에 state에 값을 할당했다.
coins state는 마운트 될 때 한번만 값이 변경될 수 있도록 설계를 했기 때문에 Dependency를 비워놨다.
useEffect을 활용해 컴포넌트 생명 주기 중 componentWillUnMount
를 다룰수 있다. 바로 CleanUp 함수를 이용하는 것이다.
useEffect(() => {
return () => { };
}, []);
위 코드를 살펴보면 useEffect의 첫 번째 인자로 주어지는 콜백함수에서 어떤 함수를 리턴하고 있는것을 확인할 수 있다. 리턴해주는 함수가 바로 CleanUp 함수이다.
해당 함수는 컴포넌트가 UnMount 될 때 실행해주는 함수이다.
const button = document.getElementById("button");
const onClick = () => console.log("hi");
useEffect(() => {
button.addEventListener("click", onClick);
return () => {
button.removeEventListener("click", onClick);
}
}, []);
위 예제에서는 useEffect를 통해서 컴포넌트가 랜더링 된 이후 버튼에 이벤트를 달아줬다. 그리고 클린업 함수를 통해 이벤트를 버튼에서 해제해줬다.
해당 CleanUp 함수는 컴포넌트가 사라질 때 (UnMount) 실행될 것이다.