React 17 RC와 이벤트 위임 변경사항

배경

회사 프로젝트에서 jQuery 레거시와 React를 함께 사용하는 페이지가 있다. 이벤트 버블링 관련 이슈가 종종 발생했는데, React 17 RC에서 이를 개선했다는 소식을 접했다.

주요 변경사항

이벤트 위임 위치 변경

React 16까지는 모든 이벤트를 document에 등록했다. React 17부터는 React 트리가 렌더링된 root DOM 컨테이너에 등록한다.

// React 16
const rootNode = document.getElementById('root');
ReactDOM.render(<App />, rootNode);
// 이벤트는 document에 등록됨

// React 17
const rootNode = document.getElementById('root');
ReactDOM.render(<App />, rootNode);
// 이벤트는 rootNode에 등록됨

e.stopPropagation() 동작 개선

React 이벤트에서 stopPropagation()을 호출하면 이제 실제로 document까지 전파되지 않는다. jQuery나 Vanilla JS 이벤트 리스너와의 충돌이 줄어든다.

function Button() {
  const handleClick = (e) => {
    e.stopPropagation();
    // React 17에서는 root DOM까지만 전파되고 멈춤
    // document의 리스너까지 가지 않음
  };
  
  return <button onClick={handleClick}>Click</button>;
}

마이그레이션

대부분의 경우 코드 변경 없이 동작한다. 다만 document 레벨 이벤트에 의존하는 코드가 있다면 검토가 필요하다.

// 이런 패턴을 사용 중이라면 주의
document.addEventListener('click', () => {
  // React 컴포넌트 내부 클릭이
  // stopPropagation 했을 때 동작이 달라질 수 있음
});

소감

No New Features라는 메이저 버전은 처음 봤다. 점진적 업그레이드를 위한 결정이라고 하는데, 실용적인 접근이라고 생각한다. 레거시 통합 프로젝트에서는 유용할 것 같다.

React 17 RC와 이벤트 위임 변경사항