【React】でDOMを操作するcreatePortalの使い方と使い所と注意点
ReactでDOMを操作するcreatePortalの使い方と使い所と注意点を紹介します。
目次から読む
ReactでDOMを操作するcreatePortalとは
createPortalというメソッドを使うことで、本来React要素のツリーで親子関係にない要素を指定することが可能になります。 createPortalは、子のDOM要素を、親子関係のないところに作成するときに使います。 マウント先のHTMLを変更できるということです。createPortalの使い方
第一引数: React の子要素としてレンダー可能なもの (要素、文字列、フラグメント、コンポーネントなど)を指定します。 第二引数: レンダー先のDOM要素を指定します。createPortalの使いどころ
子要素は親要素のスタイル(overflow、z-index、width、heightなど)によって表示に一定の制限を受けます。 その制限に関係なく、子要素を表示したいときにcreatePortalを使います。 機能として代表的なものは、モーダル、ポップアップ、トーストなどがあります。createPortalの例
まずは、createPortalを使用していないバージョンが以下になります。Sample.js
import { useState } from "react";
import { createPortal } from "react-dom";
import Modal from "./components/Modal";
const Sample = () => {
const [modalOpen, setModalOpen] = useState(false);
return (
<div className="parent">
<div className="modal__container"></div>
<button
type="button"
onClick={() => setModalOpen(true)}
disabled={modalOpen}
>
モーダルを表示
</button>
{modalOpen && <Modal handleCloseClick={() => setModalOpen(false)} />}
</div>
);
};
export default Sample;
Modal.js
import "./Modal.css";
const Modal = ({ handleCloseClick }) => {
return (
<div className="modal">
<div className="modal__content">
<p>モーダル</p>
<button type="button" onClick={handleCloseClick}>
閉じる
</button>
</div>
</div>
);
};
export default Modal;
このモーダルは、Sample.jsのparentクラスの下に表示されることになります。
実際は、modal__containerクラスの中に表示したいという場合、createPortalを使用する必要があります。
createPortalを使ったバージョン
import { useState } from "react";
import { createPortal } from "react-dom";
import Modal from "./components/Modal";
const ModalPortal = ({ children }) => {
const target = document.querySelector(".modal__container");
return createPortal(children, target);
};
const Sample = () => {
const [modalOpen, setModalOpen] = useState(false);
return (
<div className="parent">
<div className="modal__container"></div>
<button
type="button"
onClick={() => setModalOpen(true)}
disabled={modalOpen}
>
モーダルを表示
</button>
{modalOpen && (
<ModalPortal>
<Modal handleCloseClick={() => setModalOpen(false)} />
</ModalPortal>
)}
</div>
);
};
export default Sample;
まず、react-domからcreatePortalをimportします。
import { createPortal } from "react-dom";
ポータルとなるコンポーネントを作成します。
const ModalPortal = ({ children }) => {
const target = document.querySelector(".modal__container");
return createPortal(children, target);
};
上にも記述していますが、第一引数にはReactの子要素としてレンダー可能なもの(要素、文字列、フラグメント、コンポーネントなど)を指定します。
第二引数には、レンダー先のDOM要素を指定します。上の場合だと第一引数は、Modalコンポーネントで、第二引数がmodal__containerクラスとなります。
<ModalPortal>
<Modal handleCloseClick={() => setModalOpen(false)} />
</ModalPortal>
そして、最後にコンポーネントのようにして使用することができます。
これで指定したコンポーネントのマウント先のHTMLの任意の場所に変更することができます。