본문 바로가기

리액트 공식 문서 읽기

28화: Separating Events from Effects

이 글은 단순히 리액트 공식 문서를 읽고 베꼈을 뿐이다!! 학습 목적이라면 공식 문서를 보는 걸 추천한다.

 

참새. Unsplash 에 Ryan Beltz 님이 올림

공식 문서

https://react.dev/learn/separating-events-from-effects

 

Separating Events from Effects – React

The library for web and native user interfaces

react.dev

이벤트 핸들러 vs 이펙트

  • 이벤트 핸들러
    • 특정 상호작용에 반응해서 실행
    • 이용자의 관점에서 '어떤 행동(상호작용)을 했기 때문에' 무엇인가가 실행되어야 하는 경우
  • 이펙트
    • 동기화가 필요할 때 실행
    • 어떤 특정한 상호작용 때문에 실행되어야 하는 게 아님
    • '화면이 나타났다는 사실 자체만으로' 실행해야 하는 경우

반응형(리액트스러운) 값과 반응형 로직

  • 반응형 값
    • 컴포넌트 본문 안에 선언된 props, 상태, 변수들
    • 리렌더링으로 인해 값이 변할 수 있음
  • 이벤트 핸들러 안에 있는 로직
    • 반응형 로직 ㄴㄴ
    • 이용자가 같은 상호작용을 또 하기 전까지는 실행되지 않음
    • 얘네는 반응형 값의 변화에 대응하지 않으면서 그 값들을 읽을 수 있음
    • 반응형 값이 변했으니까 실행'하는게 아니라 어떤 상호작용을 했으니까 실행해야 하는 로직
  • 이펙트 안에 있는 로직
    • 반응형 로직 ㅇㅇ
    • 의존성 배열에 해당 로직이 반응해야 하는 값들을 넣음
    • 리렌더링으로 인해 해당 값들이 바뀌면 리액트는 로직을 다시 실행함
    • 값이 바뀌었으니까 다시 동기화해야 하는 것들

이펙트에서 반응형이 아닌(리액트스럽지 않은) 로직 분리하기

  • 예) 이펙트를 실행할 때 로그를 남기기 위해서 반응형 값이 필요하지만, 그 값의 변화로 인해서 로그를 남기고 싶지는 않은 경우
  • 이펙트 안에 있는 로직이지만 반응형 값의 변화에는 대응하지 않기 원할 때
  • useEffectEvent 사용 (현 시점에서 실험적인 기능이라 함)

이펙트 이벤트 (현 시점에서 실험적인 기능임)

function ChatRoom({ roomId, theme }) {
  const onConnected = useEffectEvent(() => {
    showNotification('Connected!', theme);
  });

  useEffect(() => {
    const connection = createConnection(serverUrl, roomId);

    connection.on('connected', () => {
      onConnected();
    });

    connection.connect();

    return () => connection.disconnect();
  }, [roomId]);
  // ...
  • 이펙트 로직의 일부분이지만 이벤트 핸들러처럼 동작함: 사용자의 상호작용이 아닌 이펙트가 유발한다는 차이는 있음
  • 내부 로직은 반응형이 아님. 항상 props와 상태의 최신 값들을 읽음
  • 이펙트 이벤트는 리액트스러운 값이 아니므로 의존성 배열에서 빼야 함
  • 이펙트 이벤트는 이펙트 안에서만 사용하기

이펙트 이벤트의 한계

  • 이펙트 안에서만 사용할 수 있음
  • 다른 컴포넌트나 훅에 넘길 수 없음: 넘기는 대신 거기서 이펙트 이벤트를 직접 만들어서 쓸 것

그냥 의존성 배열 관련 linter 설정 끄면 안 됨?

  • 제발 하지마