useEffect
- useEffect:
componentDidMount
,componentDidUpdate
이후에 발생하는 코드를 넣음 - 순수 함수는 참조 투명성을 가지는데 (부작용이 없음) useEffect는 이름에서 드러나듯 함수 컴포넌트가 부작용을 이용하는 도구다.
- 계속 마운트되는 부분의 라이프사이클을 관리
- 클래스 컴포넌트에서는
componentDidMount()
등의 함수를 썼었는데 넘 번거로워서 생김
직접 써보기
setInterval
로 1초마다 초를 업데이트하는 함수가 있다.
function App() {
const [second, setSecond] = useState(0);
setInterval(() => {
setSecond(second +1);
},1000);
return (
<div>
<p>{second}초</p>
</div>
)
}
이 함수의 문제점은 1초마다 함수 전체가 새로 마운트 된다는 거다.
그러면 setInterval
함수를 또 시작한다.
setInterval 안에서 console.log
함수를 찍으면 이렇게 이상한 결과가 나온다.
setInterval()
함수가 대략 1초마다 계속 실행되며 점점 쌓인다.
이런 경우에 useEffect()를 사용하면 된다!
function App() {
const [second, setSecond] = useState(0);
useEffect(()=> {
let interval = setInterval(()=> {
console.log(second);
setSecond(second+1);
}, 1000);
return () => {
clearInterval(interval);
}
}, [second]);
return (
<div className="App">
<p>{second}초</p>
</div>
)
}
이렇게 하면 마운트, 언마운트가 반복되며 second
가 1초마다 1씩 늘어난다.
useEffect(() => {
console.log("mount")
return () => {
console.log("unmount') // 언마운트(cleanup) 안 하면 요청이 반복적으로 발생
}
}, [second]); // mount에 의존적인 변수(dependencies) 삽입
추가로, useEffect 잘못 쓰고 계신겁니다.라는 글에 따르면
리액트18의 strict mode에서는 렌더링을 두번씩 하는데 그럴 경우 불필요한 상태 변경/리렌더링이 있을 수 있으니 useEffect에 클린업함수를 꼭 넣어줘라, 연산이 비싸면 useMemo 써라, react-query 등 캐시된 데이터를 써라
고 한다.