해당 포스트는 코드아카데미의 React 101 강의의 필기입니다.
첫 렌더링 이후에도 어떤 동작을 실행시키기 위해 사용하는 훅. Mounting, Updating, Unmounting phase에 필요한 side effect를 실행시킬 수 있다.
import React, { useState, useEffect } from 'react';
function PageTitle() {
const [name, setName] = useState('');
useEffect(() => {
document.title = `Hi, ${name}`;
});
return (
<div>
<p>Use the input field below to rename this page!</p>
<input onChange={({target}) => setName(target.value)} value={name} type='text' />
</div>
);
}
= effect
사용이 끝난 코드들은 제거를 해주어야 memory leak
를 방지할 수 있다.
useEffect(()=>{
document.addEventListener('keydown', handleKeyPress);
return () => {
document.removeEventListener('keydown', handleKeyPress);
};
})
return 뒤의 함수(cleanup function)가 없었다면 쓸데없이 이벤트 리스너가 계속 실행됨. 심지어 버그, 충돌까지 일으킬 수 있음.
(위와 같은 경우, 이벤트 리스너 제거를 해주지 않으면 같은 이벤트 리스너가 계속 쌓임)
Clean up 함수를 만드는 것은 개발자의 재량이므로 Memory leak를 최소화할 수 있는 방법을 항상 생각해야한다.
재렌더링 될 때마다 실행하고 싶진 않은 경우 → dependency array
를 사용한다
useEffect(()=>{}
, []
)
effect
+ clean up function
dependency array
➡️ 첫 렌더링 때는 항상 실행되지만, 이후에는 dependency array에 있는 항목이 변화될 때만 렌더링 된다.
✨ 만약 빈 배열
[]
을 dependency array로 준 경우, 첫 렌더링에만 실행되고 그 이후로는 실행되지 않는다
🔥 setInterval 코드 예시
useEffect(() => {
const intervalId = setInterval(() => {
setTime((prev) => prev + 1)
}, 1000);
return () => {clearInterval(intervalId)}
}, [])
서버에서 데이터를 가져오는 경우 특히 effect 발생 시점을 잘 관리해야함
등을 고려해야하기 때문.
💡 useState와 useEffect를 함께 사용하여 첫 렌더링 후 모든 데이터를 받아와 state에 저장하는 방법으로 한번만 통신해도 되도록 만들 수 있음.
리액트는 컴포넌트에 대한 정보 (jsx, 함수 등)을 계속 refresh 하는데, 이 때 배치 순서가 중요함. Hooks는 그래서 절대 반복문, 조건문, 혹은 하위 요소로 선언하지 않음!
나쁜 예)
if (userName !== '') {
useEffect(() => {
localStorage.setItem('savedUserName', userName);
});
}
좋은 예)
useEffect(() => {
if (userName !== '') {
localStorage.setItem('savedUserName', userName);
}
});
그리고 클래스형 컴포넌트에서 혹은 바닐라 JS에선 Hooks를 절대 사용할 수 없다!