ReactJS - ポータル:Reactアプリケーションでの新次元への扉

こんにちは、React開発者の卵さんたち!今日は、Reactのポータルの世界に一緒に飛び込みましょう。Imagine you're building a house (your React application), and suddenly you realize you need a secret passage to transport something from one room to another without going through the main hallway. That's essentially what React Portals do for your components!

ReactJS - Portals

Reactポータルとは?

Reactポータルは、親コンポーネントのDOM階層外に存在するDOMノードに子をレンダリングするための第一級の方法を提供します。簡単に言えば、wormholeを作成して、DOMツリーの別のところにコンポーネントをレンダリングすることができるようにする东西です。それも、依然としてReactのコンポーネント階層の一部としてです。

なぜポータルが必要なのか?

「なぜ私がコンポーネントをどこにでもレンダリングできないのか?」と思うかもしれません。大多数のケースでは、それは可能です!しかし、ポータルが役に立つシナリオもあります:

  1. モーダルダイアログ
  2. ツールチップ
  3. フローティングメニュー
  4. コンテナからはみ出すウィジェット

ポータルの仕組みと使い方について詳しく見ていきましょう。

最初のポータルを作成する

ポータルを作成するためには、ReactDOM.createPortal()メソッドを使用します。以下は基本的な例です:

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

function MyPortalComponent() {
return ReactDOM.createPortal(
<h1>I'm rendered somewhere else!</h1>,
document.getElementById('portal-root')
);
}

この例では、IDが 'portal-root' のDOMノードに <h1> 要素をレンダリングするポータルを作成しています。このノードは、メインのReactアプリのルート要素の外に存在する必要があります。

ReactDOM.createPortal()メソッドの構造を分解します:

  1. 第一引数はレンダリングしたいReact要素です。
  2. 第二引数はレンダリング先のDOM要素です。

実世界の例:モーダルダイアログ

より実用的な例として、アプリケーションコンテンツの上に表示されるモーダルダイアログを作成してみましょう。

import React, { useState } from 'react';
import ReactDOM from 'react-dom';

function Modal({ isOpen, onClose, children }) {
if (!isOpen) return null;

return ReactDOM.createPortal(
<div className="modal-overlay">
<div className="modal-content">
{children}
<button onClick={onClose}>Close</button>
</div>
</div>,
document.getElementById('modal-root')
);
}

function App() {
const [isModalOpen, setIsModalOpen] = useState(false);

return (
<div>
<h1>Welcome to My App</h1>
<button onClick={() => setIsModalOpen(true)}>Open Modal</button>
<Modal isOpen={isModalOpen} onClose={() => setIsModalOpen(false)}>
<h2>This is a Modal</h2>
<p>It's rendered outside the main React tree!</p>
</Modal>
</div>
);
}

この例では、再利用可能な Modal コンポーネントを作成し、ポータルを使用してコンテンツをレンダリングしています。App コンポーネントは、Reactの useState ヒookを使用してモーダルの表示を制御しています。

以下に何が起こっているかを分解します:

  1. Modal コンポーネントは、(isOpen プロパティ)に基づいて表示されるかどうかをチェックします。
  2. 表示されている場合、ポータルを使用して 'modal-root' エレメントにコンテンツをレンダリングします。
  3. モーダルコンテンツには、閉じるボタンが含まれており、onClose プロパティをトリガーします。
  4. App コンポーネントでは、状態を使用してモーダルの表示を制御します。

イベントのバブリングを通すポータル

ポータルの興味深い側面の1つは、どこにレンダリングされているかに関係なく、イベントがReactツリーを通じてバブリングすることです。以下に例を示します:

import React, { useState } from 'react';
import ReactDOM from 'react-dom';

function Parent() {
const [clicks, setClicks] = useState(0);

const handleClick = () => {
setClicks(clicks + 1);
};

return (
<div onClick={handleClick}>
<h1>Clicks: {clicks}</h1>
<Portal>
<Child />
</Portal>
</div>
);
}

function Portal({ children }) {
return ReactDOM.createPortal(
children,
document.getElementById('portal-root')
);
}

function Child() {
return <button>Click me!</button>;
}

この例では、ポータル内のボタンをクリックすると、親コンポーネントのクリックハンドラがトリガーされ、クリック数がインクリメントされます。この振る舞いは非常に役立ちます。コンポーネントが実際にどこにレンダリングされているかに関係なく、期待されるイベントの伝播が維持されます。

ベストプラクティスと考慮事項

ポータルを使用する際には、以下の点に注意してください:

  1. アクセシビリティ:ポータルコンテンツはアクセシブルにする必要があります。特にスクリーンリーダーに対応してください。
  2. イベント処理:イベントはReactツリーを通じてバブリングします。DOMツリーではありません。
  3. スタイル:ポータルコンテンツには別のスタイルの考慮が必要です。
  4. クリーンアップ:コンポーネントがアンマウントされたときにポータルをクリーンアップ забудьте.

ポータルメソッド

以下に、Reactポータルに関連する主要なメソッドの表を示します:

メソッド 説明
ReactDOM.createPortal(child, container) ポータルを作成します。child は任意のレンダリング可能なReact子要素、container はDOM要素です。
ReactDOM.unmountComponentAtNode(container) モウントされたReactコンポーネントをDOMから削除し、イベントハンドラと状態をクリーンアップします。

結論

Reactポータルは、従来のコンポーネント階層から脱出してレンダリングする強力な機能です。モーダル、ツールチップ、以及其他のUI要素を作成する際に特に役立ちます。

しかし、力には責任が伴います!ポータルを賢く使用し、アプリケーションの構造とアクセシビリティへの影響を常に考慮してください。

ハッピーコーディングを!あなたのポータルがいつも興味深い新しい次元へと導いてくれることを願っています!

Credits: Image by storyset