[React] useEffectEvent 훅

2025. 11. 11. 21:51·React

개요


React 공식 문서를 살펴보다가, 19버전에서 useEffectEvent 훅이 실험 단계(Experimental)에서 정식 훅으로 변경된 것을 보고 더 자세히 알아보기 위해 공부해보았다.

https://ko.react.dev/reference/react/useEffectEvent

 

useEffectEvent – React

The library for web and native user interfaces

ko.react.dev


 

왜 만들어진 훅인가?


 

이벤트 핸들러를 useEffect 훅을 사용해서 등록한다면 다음과 같이 작성할 수 있다.

function MyComponent() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    function onClick() {
      console.log(count); // 항상 0만 출력됨
    }
    window.addEventListener('click', onClick);
    return () => window.removeEventListener('click', onClick);
  }, []); // 의존성이 없기 때문

  return <button onClick={() => setCount((c) => c + 1)}>증가</button>;
}

위 코드는 문제가 있다.

 

onClick 이벤트를 수행하면 count를 출력하지만 클릭할 때 마다 1씩 증가하는게 아닌 0만 출력된다.

 

의존성 배열에 아무것도 들어있지 않기 때문이다.

onClick 함수가 기억하는 count의 값은 항상 0인 stale closure 문제가 발생한다.

 

이는 보통 아래와 같이 해결할 수 있다.

useEffect(() => {
  function onClick() {
    console.log(count);
  }
  window.addEventListener('click', onClick);
  return () => window.removeEventListener('click', onClick);
}, [count]);

이렇게만 해도 문제는 없다.

 

하지만 이 코드 때문에 컴포넌트가 렌더링 될 때 마다 매번 eventListener가 등록되었다가 삭제된다.

 

왜냐하면 useEffect는 ComponentDidMount, ComponentDidUpdate, ComponentWillUnmount 이 3개의 생명주기를 대체하는 훅이기 때문이다.

당장의 count 하나만 의존성으로 관리한다면 그렇게 큰 문제는 일어나지 않을 수 있지만 아래와 같은 이벤트라면?

function CanvasEditor({ scale, tool, user, color }) {
  const [x, setX] = useState(0);
  const [y, setY] = useState(0);
  const [dragging, setDragging] = useState(false);

  useEffect(() => {
    function onMouseMove(e) {
      if (!dragging) return;
      console.log(
        'x:', x,
        'y:', y,
        'scale:', scale,
        'tool:', tool,
        'user:', user.name,
        'color:', color
      );
    }

    window.addEventListener('mousemove', onMouseMove);
    return () => window.removeEventListener('mousemove', onMouseMove);

  // dependency explosion
  }, [x, y, dragging, scale, tool, user, color]);
}

x, y, dragging, scale, tool 등 많은 변수들이 의존성 배열에 들어가있고 이 중 하나라도 변경되면 생명주기를 다시 수행하게 되면서 리스너가 매번 등록&해제 될 것이다.


useEffectEvent


위와같은 문제를 해결하기 위해 나온 훅이 useEffectEvent이다.

 

useEffectEvent 훅의 목적은 항상 최신 값에 접근할 수 있는 안정적인 콜백 이다.

const onSomething = useEffectEvent(callback)

 사용 방법은 간단하다.

 

useEffectEvent 훅의 매개변수로 callback 함수를 넘겨주기만 하면 된다.

 

반환값은 Effect Event Function이다.

Effect Event Function을 반환하기 때문에 useEffect, useLayoutEffect, useInsertionEffect 훅의 내부에서 호출할 수 있다.

 

사용 예시는 아래와 같다.

import { useEffectEvent } from 'react';

function MyComponent() {
  const [count, setCount] = useState(0);

  const handleClick = useEffectEvent(() => {
    console.log(count); // 항상 최신 count 출력
  });

  useEffect(() => {
    window.addEventListener('click', handleClick);
    return () => window.removeEventListener('click', handleClick);
  }, []); // 의존성 배열 없어도됨
}

count가 변경될 때 마다 리스너가 매번 등록&삭제되는 문제가 해결되고 handleclick 함수는 항상 최신 count값을 참조할 수 있게 되었다.


주의사항


useEffectEvent로 만든 함수는 반드시 useEffect 계열 훅 안에서만 호출해야 한다.

때문에 사용할 useEffect 바로 위에 선언하는 것이 좋다.

다른 컴포넌트나 훅에 함수를 넘길 수 없다.

 

useEffectEvent는 의존성 배열을 줄이기 위한 함수가 아니다.

useEffectEvent는 오로지 stale closure 방지용이다.

 

반드시 이벤트 핸들러 내부에서만 동작하는 로직으로 작성해야 한다.

React State를 직접 변경하는 이벤트에 이 훅을 사용하는 것은 부적합하다.

'React' 카테고리의 다른 글

[React] Redux를 사용해서 간편하게 모달(modal) 구현하기  (0) 2024.03.13
[React] 컴포넌트의 생명주기(Lifecycle)  (0) 2023.02.10
[React] 프로퍼티에 필수, 기본값 지정 / 자식 프로퍼티 사용  (0) 2023.01.13
[React] 다양한 자료형 프로퍼티 사용하기  (0) 2023.01.06
[React] 프로퍼티(props) 기본  (0) 2023.01.04
'React' 카테고리의 다른 글
  • [React] Redux를 사용해서 간편하게 모달(modal) 구현하기
  • [React] 컴포넌트의 생명주기(Lifecycle)
  • [React] 프로퍼티에 필수, 기본값 지정 / 자식 프로퍼티 사용
  • [React] 다양한 자료형 프로퍼티 사용하기
MaKa_
MaKa_
이게 왜안될까요
  • MaKa_
    벌레 잡는 사람
    MaKa_
  • 전체
    오늘
    어제
    • 공부 (55) N
      • CS (18)
        • 자료구조(data structure) (7)
        • 알고리즘(Algorithm) (6)
      • React (7) N
      • React Native (2)
      • Next.js (5)
      • Backend (3)
      • 이야기 (9)
        • 회고 (4)
        • 일상 (5)
      • 기타 (8)
      • 알고리즘 문제 (2)
        • 백준 (0)
        • 프로그래머스 (1)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

    • 깃허브
  • 공지사항

  • 인기 글

  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
MaKa_
[React] useEffectEvent 훅
상단으로

티스토리툴바