prgrms-web-devcourse/FEDC4-Modern-React-Study

[10장][효중] 리액트 17과 18의 변경 사항 살펴보기

Closed this issue · 1 comments

퀴즈

이 코드는 React 16버전과 17버전에서 다르게 동작하는데요.!!
왜 다르게 동작하는지 설명해주세요!!

export default function App() {
    useEffect(() => {
        document.addEventListener('click',(e) => {
            console.log('이벤트가 document까지 올라감')
        },[])
    },[])

    function 안녕(e:MouseEvent<HTMLButtonElement>){
        e.stopPropagation()
        alert('안녕!')
    }
    return <button onClick = {안녕}>버튼</button>
}

ReactDOM.render(<App />,document.getElementById('root'))

정답
React 16 버전에서는 'document'에 이벤트 리스너를 직접 추가하는 방식을 사용했습니다. 따라서, useEffect에서 document에 'click' 이벤트 리스너를 추가하면 이벤트 버블링이 일어날 때, 'document'까지 이벤트가 전파되어 '이벤트가 document까지 올라감'이라는 메시지가 콘솔에 출력됩니다.

하지만 React 17 버전에서는 이벤트 위임 방식이 변경되었습니다.
이제 이벤트 리스너는 루트 DOM 노드가 아니라, React가 관리하는 가장 상위의 루트 컴포넌트에 추가됩니다.
따라서 '안녕' 함수에서 stopPropagation()을 호출하면, React의 이벤트 시스템 내부에서 이벤트 전파가 중단되므로 useEffect에서 추가한 'document'의 이벤트 리스너는 실행되지 않습니다. 이로 인해 '이벤트가 document까지 올라감'이라는 메시지가 콘솔에 출력되지 않습니다.

댓글 작성법

(다음과 같이 답을 작성해 댓글로 달아주세요)
<details>
<summary>정답</summary>
<div markdown="1">
정답 설명
</div>
</details>

정답

16버전은 이벤트가 document에 할당되어서 전파를 막으려 해도 이미 document에 등록되었기 때문에 막지 못한다.
하지만 17버전은 최상단 컴포넌트인 루트에 이벤트를 할당하기 때문에 원하는 대로 이벤트 전파를 막을 수 있다.