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 |
댓글