46
33

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

ReactDOM.createPortalを使ってモーダルを作る

Posted at

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を操作することで行う。
46
33
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
46
33

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?