WordPress のブロックエディターで SlotFill が使えない場所にボタンを表示したいときは createPortal が便利!

WordPress のブロックエディターの UI の拡張(設定パネルを追加したり、ツールバーにボタンを追加したり)では、基本的に SlotFill を使います。ですが、UI を拡張したい場所に Slot(差し込みポイント)が存在しない場合はどうしたら良いのでしょうか?という問題に createPortal を使うことで対応できたので、そのことについて書きたいと思います。

SlotFill とは何か

SlotFill は「Slot」と「Fill」という2つの仕組みで構成されます。

  • Slot:エディター内にあらかじめ用意された挿入ポイント(WordPress 的に言えばアクションフック的な感じ)
  • FillSlot に注入されるコンテンツ(ButtonToggleControlTextControl など)

よく利用される Slot の例としては下記のようなものがあります。

  • InspectorControls(ブロックの設定パネル)
  • BlockControls(ブロックツールバー)
  • PluginDocumentSettingPanel(ドキュメントの設定パネル)

下記はブロックツールバーにボタンを追加する例。

<BlockControls>
	<ToolbarButton
		icon={ shuffle }
		label={ __( 'Shuffle child blocks', 'unitone' ) }
		onClick={ shuffleInnerBlocks }
	/>
</BlockControls>

SlotFill はあくまで「WordPress があらかじめ用意している差し込みポイント」にしかコンポーネントを追加できません。そのため、コンポーネントを表示したい場所に Slot が用意されていない場合は、別の方法でコンポーネントを追加する必要があります。

createPortal とは何か

React.createPortal は、React コンポーネントの描画先を 任意の DOM 要素 に移すための仕組みです。下記のようなコードで、childtargetElement の中(最後)に追加できます。

createPortal(child, targetElement)

SlotFill が使えない場所にボタンを配置する

下記は、unitone でワイヤーフレームジェネレーターの起動ボタンをブロックエディター自体のツールバー(ブロックのツールバーではない)に追加している例です(いろいろ省略して必要な部分だけ記述しています)。

import { createPortal } from '@wordpress/element';

const PluginSidebarWireFrameGenerator = () => {
	// ↓ここにボタンを追加したい
	const toolbar = document.querySelector( '.editor-header__toolbar' );
	...

	return (
		<>
			{ toolbar &&
				createPortal(
					<WireFrameGeneratorButton { ...{ isOpen, setIsOpen } } />,
					toolbar
				) }

			{ isOpen && (
				<WireframeGeneratorModal .../>
			) }
		</>
	);
};

registerPlugin( 'unitone-wireframe-generator', {
	render: PluginSidebarWireFrameGenerator,
} );
inc2734のアバター

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です