Portals
React16で導入された概念で、子コンポーネントを親要素のDOM階層の外にレンダリングすることが可能になる。モーダルを作成する際に利用することで、ルート要素の直下にモーダルを置かなくても、子要素の中で通常のコンポーネントと同様に扱うことができる。
ソースコード
モーダルのコンポーネント作成
modal.js
import React from 'react';
import ReactDOM from 'react-dom';
import PropTypes from 'prop-types';
class Modal extends React.Component {
constructor(props) {
super(props);
this.rootEl = document.getElementById('root');
}
render() {
return(
ReactDOM.createPortal(
<div
style={{
position: 'fixed',
width: '100%',
height: '100%',
backgroundColor: 'rgba(0, 0, 0, 0.5)',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
top: 0,
left: 0,
}}
>
<div
style={{
position: 'fixed',
width: '50%',
height: '50%',
backgroundColor: 'white',
}}
>
<button onClick={this.props.onClose}>Close</button>
</div>
</div>,
this.rootEl)
);
}
}
Modal.protoTypes = {
onClose: PropTypes.func,
}
export default Modal;
-
this.rootEl = document.getElementById('root');
でルートのDOM要素を取得。 -
ReactDOM.createPortal
で取得したルート要素の直下に、モーダルを描画する。
使い方
sample.js
import React from 'react';
import ReactDOM from 'react-dom';
import Modal from './modal';
class Sample extends React.Component {
constructor(props) {
super(props);
this.state = {
isModalShown: false,
};
}
render() {
return(
<div>
<button onClick={() => { this.setState({ isModalShown: true }) }}>Click to show modal.</button>
{this.state.isModalShown &&
<Modal onClose={() => { this.setState({ isModalShown: false }) }} />
}
</div>
);
}
}
export default Sample;
- 本来このようにModalコンポーネントを配置すると、DOMノード上でSampleの下に配置されてしまうが、createPortalを利用しているので、ルート要素の直下にModalコンポーネントが配置される。
- またコンポーネントとしては通常の子コンポーネントと同様にpropsなどを渡すことができる。
- モーダルの開閉は親要素のstateを操作することで行う。