ポータルを使って親コンポーネントの外にある箇所に子コンポーネントをレンダーする

Posted: 2020/12/13
React/
Others

React のポータルを用いれば、子コンポーネントを親要素の DOM 階層の外のある箇所にレンダリングすることができます。例えばモーダルやダイアログを実装しようとした時にルート要素の直下にコンポーネントを配置する必要がなくなります。

それでは詳しく見ていきましょう。

ポータルの定義

ポータルを作成するには以下のようにします。

ReactDOM.createPortal(child, container);

第一引数で React のコンポーネントを指定し、第二引数では DOM 要素を指定します。

簡単な例を見ていきましょう。

ダイアログを実装

では、例としてダイアログをポータルを用いて表示していきましょう。

まずダイアログを表示する DOM 要素を定義します。以下は React アプリの最上位に位置する App コンポーネントとします。そしてダイアログのコンポーネントを持つ親コンポーネントを Menu コンポーネントとします。

App コンポーネントは以下のようになり、Menu コンポーネントの親要素の外にダイアログを表示する DOM 要素が定義されていることがわかります。

import React from "react";
import Menu from "./Menu";

export default function App() {
  return (
    <>
      {/*ダイアログを表示するDOM要素*/}
      <div id="dialog" />
      <div className="App">
        <Menu />
      </div>
    </>
  );
}

では次にダイアログの親コンポーネントである Menu コンポーネントを実装します。ボタンをクリックした時にダイアログが表示されるように、useStateを用いてダイアログの開閉条件を state で管理しています。

import React, { useState } from "react";
import Dialog from "./Dialog";

const Menu = () => {
  const [isOpen, setIsOpen] = useState(false);
  const handleClick = () => {
    isOpen ? setIsOpen(false) : setIsOpen(true);
  };
  return (
    <div className="menu">
      <button onClick={handleClick}>show dialog</button>
      {isOpen && <Dialog />}
    </div>
  );
};

export default Menu;

そして、今回のメイントピックであるポータルを用いたダイアログ(Dialog)コンポーネントについて見ていきましょう。

冒頭で説明したReactDOM.createPortal(child, container) 構文を用いて、dialogという id の要素に第一引数で指定した要素をレンダリングしていることがわかります。これでボタンを押すと dialog の表示・非表示を切り替えることができます。

import React from "react";
import ReactDOM from "react-dom";

const Dialog = () => {
  return ReactDOM.createPortal(
    <h2>This is dialog</h2>,
    document.getElementById("dialog")
  );
};

export default Dialog;

ポータルをうまく使いこなして、ダイアログやモーダルの実装に役立ててください!

それでは 🙌