실행되어야 하는 작업이지만 현 컴포넌트 렌더링 과정에 직접적이고 즉각적인 영향을 미치지 않는 것
예를 들어, 여러 나라의 이름을 요소로하는 배열이 있고 사용자의 위치와 가까운 순서대로 이 배열을 정렬한다고 하면 사용자의 위치를 전달하고 거리를 구하는 로직은 side effect라고 할 수 있다. 왜냐하면 그 로직이 앱에 필요하기는 하지만 컴포넌트의 주된 목적인 렌더링이 가능한 jsx 코드를 반환하는 것과 같은 직접적인 연관성이 없기 때문이다.
추가로 클릭에 대한 이벤트 리스너 설정이나 useState 등이 있다면 이것은 화면에 보여지는 것이기 때문에 side effect라고 할 수 없다.
위 사용자 위치를 기준으로 정렬된 배열 데이터를 화면에 나타내기 위해 useState로 관리하게 된다면 다음과 같은 현상이 발생한다.
위 문제를 해결하기 위해 useEffect 훅을 사용할 수 있다.
useEffect(이펙트 함수, 의존성 배열);
function App() {
const [places, setPlaces] = useState([]);
useEffect(() => {
// 1. 사용자 정보를 취득하고 이를 기준으로 배열 데이터를 정렬
sortedPlaces =
...
// 2. 상태 업데이트
setPlaces(sortedPlaces)
}, [])
}
모든 사이드 이펙트에 useEffect를 사용하는 것은 아니다. 이펙트 함수로는 컴포넌트가 실행된 이후, 렌더링 이후에 실행되어도 되는 작업 로직들을 작성해야한다.
이펙트 함수가 실행되는 때를 정리해보면
useEffect의 이펙트 함수가 반환하는 함수로, 컴포넌트가 언마운트되기 전이나 업데이트되기 직전에 수행할 작업이 있는 경우 사용한다.
함수도 객체 값이기 때문에 매번 실행될 때마다 새롭게 정의된다. 따라서, 함수를 의존성 배열에 넣으면 컴포넌트가 실행될 때마다 함수 의존성이 변한 것으로 인식해 이펙트 함수를 실행시키게 되고 만약 거기에 상태를 업데이트하는 함수가 있다면 무한 루프에 빠질 수가 있다.
이를 위해 함수가 매번 재정의 되지 않도록 하는 useCallback 훅을 사용할 수 있다. useEffect와 마찬가지로 의존성 배열에 있는 값이 변했을 때만 해당 함수를 정의하게끔한다.