useEffect

양세희·2022년 5월 30일
0
post-thumbnail
post-custom-banner

useEffect

useEffect(didUpdate);

명령형 또는 어떤 effect를 발생하는 함수를 인자로 받는다.

변형, 구독, 타이머, 로깅 또는 다른 부작용(side effect)은 (React의 렌더링 단계에 따르면) 함수 컴포넌트의 본문 안에서는 허용되지 않는다. 이를 수행한다면 매우 혼란스러운 버그 및 UI의 불일치를 야기하게 될 것이다.

대신에 useEffect를 사용하자. useEffect에 전달된 함수는 화면에 렌더링이 완료된 후에 수행될 것이다.

기본적으로 동작은 모든 렌더링이 완료된 후에 수행되지만, 어떤 값이 변경되었을 때만 실행되게 할 수도 있다.

effect 정리

effect는 종종 컴포넌트가 화면에서 제거될 때 정리해야 하는 리소스를 만든다. 구독이나 타이머 ID와 같은 것이 이에 해당한다. 이것을 수행하기 위해서 useEffect로 전달된 함수는 정리(clean-up) 함수를 반환할 수 있다. 아래는 구독을 생성하는 예시이다.

useEffect(() => {
  const subscription = props.source.subscribe();
  return () => {
    // Clean up the subscription
    subscription.unsubscribe();
  };
});

정리 함수는 메모리 누수 방지를 위해 UI에서 컴포넌트를 제거하기 전에 수행된다. 더불어, 컴포넌트가 여러 번 렌더링 된다면 다음 effect가 수행되기 전에 이전 effect는 정리된다. 위의 예시에서, 매 갱신마다 새로운 구독이 생성된다고 볼 수 있는 것이다.

effect 타이밍

conponentDidMountcomponentDidUpdate와는 다르게, useEffect로 전달된 함수는 지연 이벤트 동안에 레이아웃 배치와 그리기를 완료한 후 발생한다. 이것은 구독이나 이벤트 핸들러를 설정하는 것과 같은 다수의 공통적인 부작용에 적합하다. 대부분의 작업이 브라우저에서 화면을 업데이트 하는 것을 차단해서는 안되기 때문이다.

하지만 모든 effect가 지연될 수는 없다. 예를 들어 사용자에게 노출되는 DOM 변경은 사용자가 노출된 내용의 불일치를 경험하지 않도록 다음 화면을 다 그리기 전에 동기화 되어야 한다. 이런 종류의 effect를 위해 React는 useLayoutEffect라는 추가적인 Hook을 제공한다. 이것은 useEffect와 동일한 시그니처를 가지고 있고, 이것이 수행될 때에만 차이가 난다.

useEffect는 브라우저 화면이 다 그려질 때가지 지연되지만, 다음 새로운 렌더링이 발생하기 이전에 발생하는 것도 보장한다. React는 새로운 갱신을 시작하기 전에 항상 이전 렌더링을 완료한다.

조건부 effect 발생

effect의 기본 동작은 모든 렌더링을 완료한 후 effect를 발생하는 것이다. 이와 같은 방법으로 의존성 중 하나가 변경된다면 effect는 항상 재생성된다.

그러나 이것은 이전 위의 구독 예시와 같이 일부의 경우에는 과도한 작업일 수 있다. source props가 변경될 때에만 필요한 거라면 매번 갱신할 때마다 새로운 구독을 생성할 필요는 없다.

이것을 해결하려면 useEffect의 두 번째 인자를 전달하면 된다. 이 인자는 effect가 종속되어 있는 값의 배열이다. 이를 적용한 예는 아래와 같다.

useEffect(
  () => {
    const subscription = props.source.subscribe();
    return () => {
      subscription.unsubscribe();
    };
  },
  [props.source],
);

이렇게 하면 props.source가 변경될 때에만 구독이 재생성될 것이다.

의존성 값의 배열은 effect 함수의 인자로 전달되지 않는다. 하지만 개념적으로는, 이 기법은 effect 함수가 무엇일지를 표현하는 방법이다. effect 함수 안에서 참조되는 모든 값은 의존성 값의 배열에 드러나야 한다

post-custom-banner

0개의 댓글