본문 바로가기
Front-End/React

React Portal

by sharekim 2023. 10. 6.

https://ko.legacy.reactjs.org/docs/portals.html

 

Portals – React

A JavaScript library for building user interfaces

ko.legacy.reactjs.org

React Portal 은 부모 컴포넌트의 DOM 계층 바깥에서 DOM 노드를 렌더링하는 방법이다.

<div id="app-root"></div>
<div id="modal-root"></div>

위와 같이 메인 app 의 <div> 영역 바깥에 modal 을 표현할 수 있는 <div> 를 생성할 때 쓰이는데,

이는 부모의 z-index 값이 작은 경우(예를 들어 1), 자식 컴포넌트의 z-index 가 커도 화면 상단으로 표시되지 않을 때

app-root 바깥에 modal-root 를 둠으로써 해결할 수 있다.

 

React.createPortal 로 만들어진 요소는 app-root 내의 요소로 이벤트 버블링이 가능하다.

아래는 React 자습서의 예시

/ 여기 이 두 컨테이너는 DOM에서 형제 관계입니다.
const appRoot = document.getElementById('app-root');
const modalRoot = document.getElementById('modal-root');

class Modal extends React.Component {
  constructor(props) {
    super(props);
    this.el = document.createElement('div');
  }

  componentDidMount() {
    // Portal 엘리먼트는 Modal의 자식이 마운트된 후 DOM 트리에 삽입됩니다.
    // 요컨대, 자식은 어디에도 연결되지 않은 DOM 노드로 마운트됩니다.
    // 자식 컴포넌트가 마운트될 때 그것을 즉시 DOM 트리에 연결해야만 한다면,
    // 예를 들어, DOM 노드를 계산한다든지 자식 노드에서 'autoFocus'를 사용한다든지 하는 경우에,
    // Modal에 state를 추가하고 Modal이 DOM 트리에 삽입되어 있을 때만 자식을 렌더링해주세요.
    modalRoot.appendChild(this.el);
  }

  componentWillUnmount() {
    modalRoot.removeChild(this.el);
  }

  render() {
    return ReactDOM.createPortal(
      this.props.children,
      this.el
    );
  }
}
class Parent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {clicks: 0};
    this.handleClick = this.handleClick.bind(this);
  }

  handleClick() {
    // 이것은 Child에 있는 버튼이 클릭 되었을 때 발생하고 Parent의 state를 갱신합니다.
    // 비록 버튼이 DOM 상에서 직계 자식이 아니라고 하더라도 말입니다.
    this.setState(state => ({
      clicks: state.clicks + 1
    }));
  }
  render() {
    return (
      <div onClick={this.handleClick}>
        <p>Number of clicks: {this.state.clicks}</p>
        <p>
          Open up the browser DevTools
          to observe that the button
          is not a child of the div
          with the onClick handler.
        </p>
        <Modal>
          <Child />
        </Modal>
      </div>
    );
  }
}

function Child() {
  // 이 버튼에서의 클릭 이벤트는 부모로 버블링됩니다.
  // 왜냐하면 'onClick' 속성이 정의되지 않았기 때문입니다.
  return (
    <div className="modal">
      <button>Click</button>
    </div>
  );
}
const root = ReactDOM.createRoot(appRoot);
root.render(<Parent />);

 

'Front-End > React' 카테고리의 다른 글

React: flushSync 활용 beforeprint, afterprint 이벤트 처리  (0) 2024.08.01
Next Module Alias @  (0) 2023.09.22
React snippets  (0) 2023.09.20
TypeError Cannot read property 'setState' of undefined  (0) 2022.02.10

댓글