본문 바로가기
Dev/React.js

[React18] 13. Effect에서 이벤트 분리 및 의존성 제거 (useEffect)

by YummYum 2023. 10. 6.

 

이벤트 핸들러와 Effect 중에 선택하기

이벤트 핸들러는 같은 상호작용을 반복하는 경우에만 재실행됩니다(수동). Effect는 이벤트 핸들러와 달리 마지막 렌더링 때와 다르면 다시 동기화합니다(자동).

 

이벤트 핸들러 내부의 로직은 변화에 반응하지 않으면서 반응형 값을 읽을 수 있습니다(반응형 X).  Effect 내부의 로직은 반응형 값을 읽는 경우 그 값을 의존성으로 지정해 값이 변경되는 경우 React가 새로운 값으로 Effect 로직을 다시 실행합니다 (반응형 O).  

 

Effect 이벤트의 한계

의존성 배열에 여러 값이 들어있지만 값 중에 하나가 변경되더라도 Effect가 실행해서는 안 되는 값이 있습니다. 이때 비반응형 로직을 Effect에서 추출하려면 useEffectEvent라는 특수 Hook을 사용합니다. (useEffectEvent는 아직 출시하지 않은 실험적인 API로 오직 Effect 내부에서만 호출되며, Effect의 코드 중 비반응형입니다.)

 

function Page({ url }) {
  const { items } = useContext(ShoppingCartContext);
  const numberOfItems = items.length;

  const onVisit = useEffectEvent(visitedUrl => {
    logVisit(visitedUrl, numberOfItems);
  });

  useEffect(() => {
    onVisit(url);
  }, [url]); 
}

 


Effect 의존성 제거하기

Effect의 의존성을 선택할 수 없으며, Effect의 코드에서 사용되는 모든 반응형 값은 의존성 목록에 선언되어야 합니다. 만약 의존성을 제거하려면 해당 컴포넌트가 의존성이 될 필요가 없다는 것을 린터에 “증명”해야 합니다.

 

의존성을 변경하려면 코드를 변경해야 합니다. 먼저 Effect의 코드 또는 반응형 값 선언 방식을 변경합니다. 그런 다음, 변경한 코드에 맞게 의존성을 조장합니다. 의존성 목록이 마음에 들지 않으면 다시 코드를 변경합니다.

 

불필요한 의존성을 제거하기 위해서는 몇 가지 질문에 답해야 합니다. 

1. 이 코드를 이벤트 핸들러로 옮겨야 하나요?

2. Effect가 관련 없는 여러 가지 작업을 수행하나요?

3. 다음 state를 계산하기 위해 어떤 state를 읽고 있나요?

messages를 의존성으로 있기 때문에 새로운 메시지가 있을 때마다 채팅이 다시 연결됩니다. 

 

function ChatRoom({ roomId }) {
  const [messages, setMessages] = useState([]);
  useEffect(() => {
    const connection = createConnection();
    connection.connect();
    connection.on('message', (receivedMessage) => {
      setMessages([...messages, receivedMessage]);
    });
    return () => connection.disconnect();
  }, [roomId, messages]); 
}

 

이 문제를 해결하려면 Effect 내에 messages를 의존성에 제외하고 업데이터 함수를 setMessages에 전달해야 합니다.

 

function ChatRoom({ roomId }) {
  const [messages, setMessages] = useState([]);
  useEffect(() => {
    const connection = createConnection();
    connection.connect();
    connection.on('message', (receivedMessage) => {
      setMessages(msgs => [...msgs, receivedMessage]);
    });
    return () => connection.disconnect();
  }, [roomId]);
}

 

4. 값의 변경에 반응하지 않고 값을 읽고 싶은가요? (useEffectEvent)

5. 일부 반응형 값이 의도치 않게 변경되나요?

객체, 함수 의존성으로 인해 Effect이 필요 이상으로 재동기화될 수 있습니다. 정적 객체와 함수를 컴포넌트 외부로 이동하거나 Effect 내로 코드를 이동할 수 있습니다. 부모로부터 받은 props를 의존성으로 할 경우 부모 컴포넌트가 재렌더링할 때마다 Effect이 다시 연결됩니다. 

 


** React18 공식 문서 보고 정리한 내용입니다.

https://ko-react-exy5xcwjj-fbopensource.vercel.app/learn/separating-events-from-effects

 

Effect에서 이벤트 분리하기 – React

The library for web and native user interfaces

ko.react.dev

https://ko-react-exy5xcwjj-fbopensource.vercel.app/learn/removing-effect-dependencies

 

Effect 의존성 제거하기 – React

The library for web and native user interfaces

ko.react.dev

'Dev > React.js' 카테고리의 다른 글

[React18] 14. Custom Hook  (0) 2023.10.07
[React18] 12. Effect의 생명주기 (useEffect)  (0) 2023.10.05
[React18] 11. Effect 작성하는 법 (useEffect)  (0) 2023.10.04
[React18] 10. ref  (1) 2023.10.03
[React18] 9. context  (0) 2023.10.02

댓글