부모 컴포넌트의 DOM 계층 구조 바깥에 있는 DOM 노드로 자식을 렌더링하는 방법.
모달을 만들 때 계층 구조 상에서 자식 노드(모달)가 부모 요소들보다 더 앞에서 보이려면 z-index를 사용하거나 해야 한다. 이렇게 부모 자식 관계를 손상시키거나 거추장스러운 방법을 사용하지 않고 기본적으로 루트 노드, 루트 document에서 모달을 만든 다음 이를 하위 요소, 모달을 트리거 할 수 있는 요소에 마운트해서 보여질 수 있게 할 수 있다. 즉, 부모 노드에 종속되지 않는 요소를 만들기 위한 방법이다.
매 컴포넌트마다 따로따로 만들 필요 없이 재사용이 가능하다는 것도 장점.
기본적으로 그냥 리액트 앱을 사용할 때는 index.html에 modal 요소를 추가하는 것으로 최상위 DOM 요소에 모달을 더해준다.
만약 Next js를 사용하는 어플리케이션에서는, HTML 문서는 빌드 때에 만들어지므로 index.html이 없다. 이 때 사용하는 것이 pages/_document.js 이다.
이제 모달 요소에서 createPortal을 사용해 해당 요소 내에서 모달이 렌더링되도록 추가해준다.
이렇게 DOM 트리에서 최상단에 만들어 준 modal 요소들은 각각 하위 요소에서 ReactDOM.createPortal
을 사용해 해당 요소의 자식으로써 렌더링된다.
신기하게 DOM 트리에선 부모와 자식 관계가 아니지만 리액트 트리에서는 부모 자식 관계를 가지기 때문에 이벤트 위임도 일어날 수 있다.
ReactDOM.createPortal(childElement, container)
첫번째 인자는 렌더링할 React 자식이다. 우리는 모달 컴포넌트를 만들어서 이 첫째 인자에 집어넣을 것이다.
둘째는 우리가 이 자식 요소를 추가할 DOM 부모 요소이다. 위에서 루트 DOM 요소에 ‘#modal-root’
를 만들었으므로, 이 요소를 둘째 인자로 넣으면 된다.