ネストしたブロック: InnerBlocks の使用

他のブロックをネストするブロックを作成するには InnerBlocks コンポーネントを使用します。このコンポーネントは「カラム (Columns、複数形)」ブロックや「ソーシャルリンク」ブロックなど、他のブロックを含むブロックで使用されています。

注意: 単一のブロックは、1つの InnerBlocks コンポーネントのみを含むことができます。

基本的な InnerBlocks の使用方法

import { registerBlockType } from '@wordpress/blocks';
import { InnerBlocks, useBlockProps } from '@wordpress/block-editor';

registerBlockType( 'gutenberg-examples/example-06', {
	// ...

	edit: () => {
		const blockProps = useBlockProps();

		return (
			<div { ...blockProps }>
				<InnerBlocks />
			</div>
		);
	},

	save: () => {
		const blockProps = useBlockProps.save();

		return (
			<div { ...blockProps }>
				<InnerBlocks.Content />
			</div>
		);
	},
} );

許可されるブロック

allowedBlocks prop を使用するとさらに制限でき、block.json の allowedBlocks フィールドに加えて、このブロックの直接の子孫として挿入できるブロックを指定できます。これは個別のブロックごとに、動的に許可するブロックのリストを決定する際に便利です。例えば、ブロック属性によって決定できます。

const { allowedBlocks } = attributes;
//...
<InnerBlocks allowedBlocks={ allowedBlocks } />;

許可されるブロックのリストが常に同じ場合は、代わりに allowedBlocks ブロック設定を使用します。後述の「child ブロックの関係の定義」を参照してください。

Top ↑

orientation

デフォルトでは、InnerBlocks は、縦のリストとしてブロックが表示されることを期待しています。また、内部ブロックのラッパーに CSS flex や grid プロパティを追加して、横に並べて表示するようスタイリングすることもできます。ブロックを横に並べる場合は、horizontal レイアウトが使用されることを示すために orientation プロパティを使用してください。

<InnerBlocks orientation="horizontal" />

このプロパティを指定しても、内側のブロックのレイアウトには影響しませんが、子ブロックのブロック移動アイコンが水平に表示され、また、ドラッグアンドドロップが正しく動作するようになります。

Top ↑

デフォルトブロック

デフォルトでは InnerBlocks はブロックアペンダがクリックされると allowedBlocks によって許可された、ブロックのリストを開きます。defaultBlock プロパティを使用すると、最初のブロックアペンダがクリックされたときに挿入されるデフォルトのブロックとその属性を変更できます。例えば

<InnerBlocks defaultBlock={['core/paragraph', {placeholder: "Lorem ipsum..."}]} directInsert />

デフォルトでこの動作は directInsert プロップが true に設定されるまで無効です。これにより、デフォルトのブロックを挿入すべきかそうでないかの条件を指定できます。

Top ↑

テンプレート

template プロパティを使用して、InnerBlocks コンポーネントが挿入された際にデフォルトで含まれるブロックの集合を定義できます。ブロックの属性を設定して使用例を定義できます。次の例は InnerBlocks コンポーネントを使用した本のレビューのテンプレートです。placeholder 値を設定してブロックの使用例を示しています。

const MY_TEMPLATE = [
	[ 'core/image', {} ],
	[ 'core/heading', { placeholder: 'Book Title' } ],
	[ 'core/paragraph', { placeholder: 'Summary' } ],
];

//...

	edit: () => {
		return (
			<InnerBlocks
				template={ MY_TEMPLATE }
				templateLock="all"
			/>
		);
	},

templateLock プロパティを使用するとテンプレートをロックできます。テンプレートを完全にロックするには all を使用します。insert は追加ブロックのインサートを禁止しますが、既存のブロックは並べ替えられます。詳細については templateLock のドキュメントを参照してください。

Top ↑

投稿テンプレート

InnerBlocks とは関連しませんが、投稿タイプごとに投稿テンプレートを作れます。投稿テンプレートはブロックエディターにブロックの集合をプリロードします。

InnerBlocks テンプレートは、作成した単一ブロック内のコンポーネントのためのもので、投稿のそれ以外の箇所にはユーザーが好きなブロックを含められます。投稿テンプレートを使用すると、投稿全体を定義したテンプレートのみに固定できます。

add_action( 'init', function() {
	$post_type_object = get_post_type_object( 'post' );
	$post_type_object->template = array(
		array( 'core/image' ),
		array( 'core/heading' )
	);
} );

Top ↑

ブロックでの parent 関係、ancestor 関係、children 関係の使用

InnerBlock を使用する一般的なパターンは、その親ブロックが挿入された場合にのみ使用できる、カスタムブロックの作成です。これにより、ビルダーはブロック間の関係を確立し、ネストするブロックの発現を制限できます。ビルダーが使用できる関係には3つあります:parentancestorallowedBlocks です。違いは以下のとおりです。

  • parent を割り当てると、ネストするブロックが 親の直接の子孫 としてのみ使用、挿入できることの表明になります。
  • ancestor を割り当てると、ネストするブロックが 親の子孫 としてのみ使用、挿入できることの表明になります。
  • allowedBlocks を割り当てると、逆方向の関係の表明になります。つまり このブロックの直接の子孫 として、どのブロックを使用、挿入できるかの表明になります。

parent と ancestor の主な違いとして、parent はより細かな特異性を持ち、ancestorはそのネスト階層においてより大きな柔軟性を持ちます。

Top ↑

parent ブロック関係の定義

この例として「カラム (Column)」ブロックがあり、parent ブロック設定が割り当てられています。これにより、Column ブロックは、親の「カラム (Columns、複数形)」ブロックのネストした直接の子孫としてのみ利用できます。Columns ブロック以外では、Column ブロックはブロックインサーターのオプションとして利用できません。Column ブロックのコードを参照してください。

直接の子孫ブロックを定義する際には、parent ブロック設定を使用して、どのブロックが親であるかを定義します。これでネストするブロックは、定義された InnerBlock 以外でインサーター内には表示されません。

{
	"title": "Column",
	"name": "core/column",
	"parent": [ "core/columns" ],
	// ...
}

Top ↑

ancestor ブロック関係の定義

この例として「コメントの投稿者名」ブロックがあり、ancestor ブロック設定が割り当てられています。これにより、コメントの投稿者名ブロックは、その祖先であるコメントテンプレートブロックのネストされた子孫としてのみ利用できます。コメントテンプレートブロック以外では、コメントの投稿者名ブロックはブロックインサータのオプションとして利用できません。コメントの投稿者名ブロックのコードを参照してください。

ancestor 関係により、コメントの投稿者名ブロックは階層ツリーのどこにでも置けます。親のコメントテンプレートブロックの直接の子のみには縛られません。ただしコメントテンプレートブロックがある場合にのみ、ブロックインサーター内で挿入可能なオプションとして表示されます。

子孫ブロックを定義する際には、ancestor ブロック設定を使用します。これでネストするブロックは、定義された InnerBlock 以外でインサーター内には表示されません。

{
	"title": "Comment Author Name",
	"name": "core/comment-author-name",
	"ancestor": [ "core/comment-template" ],
	// ...
}

Top ↑

children ブロック関係の定義

この例として「ナビゲーション」ブロックがあり、allowedBlocks ブロック設定が割り当てられています。これにより、ブロックタイプの特定のサブセットのみを、ナビゲーションブロックの直接の子孫として利用できます。ナビゲーションブロックのコードを参照してください。

allowedBlocks の設定はカスタムブロックの作成者により拡張できます。カスタムブロックは blocks.registerBlockType フィルタにフックし、自身をナビゲーションブロックの利用可能な子として追加できます。

挿入可能な子孫ブロックのセットを定義する際には、allowedBlocks ブロック設定を使用します。新しい子ブロックを挿入するときにインサーターに表示されるブロックが制限されます。

{
	"title": "Navigation",
	"name": "core/navigation",
	"allowedBlocks": [ "core/navigation-link", "core/search", "core/social-links", "core/page-list", "core/spacer" ],
	// ...
}

Top ↑

React フックの使用

React フック useInnerBlocksProps を、InnerBlocks コンポーネントの代わりに使用できます。このフックを使用すると、インナーブロック領域のマークアップをより詳細に制御できます。

useInnerBlocksProps は InnerBlocks コンポーネント自身と同様に @wordpress/block-editor パッケージからエクスポートされ、InnerBlocks コンポーネントのすべてをサポートします。また、useInnerBlocksProps は useBlockProps フックと同様に機能します。

基本的な useInnerBlocksProps フックの使用方法です。

import { registerBlockType } from '@wordpress/blocks';
import { useBlockProps, useInnerBlocksProps } from '@wordpress/block-editor';

registerBlockType( 'gutenberg-examples/example-06', {
	// ...

	edit: () => {
		const blockProps = useBlockProps();
		const innerBlocksProps = useInnerBlocksProps();

		return (
			<div { ...blockProps }>
				<div {...innerBlocksProps} />
			</div>
		);
	},

	save: () => {
		const blockProps = useBlockProps.save();
		const innerBlocksProps = useInnerBlocksProps.save();

		return (
			<div { ...blockProps }>
				<div {...innerBlocksProps} />
			</div>
		);
	},
} );

また、useBlockProps から返されたオブジェクトを useInnerBlocksProps フックに渡せます。この手法により作成する要素の数を減らせます。

import { registerBlockType } from '@wordpress/blocks';
import { useBlockProps, useInnerBlocksProps } from '@wordpress/block-editor';

registerBlockType( 'gutenberg-examples/example-06', {
	// ...

	edit: () => {
		const blockProps = useBlockProps();
		const innerBlocksProps = useInnerBlocksProps( blockProps );

		return (
			<div {...innerBlocksProps} />
		);
	},

	save: () => {
		const blockProps = useBlockProps.save();
		const innerBlocksProps = useInnerBlocksProps.save( blockProps );

		return (
			<div {...innerBlocksProps} />
		);
	},
} );

上のコードはエディター内で次のマークアップをレンダーします。

<div>
	<!-- Inner Blocks get inserted here -->
</div>

フックによるアプローチを使用するもう一つの利点は、単なるオブジェクトである戻り値を分解して、react children を取得できる点です。このプロパティには実際の子のインナーブロックが含まれているため、インナーブロックと同じレベルに要素を配置できます。

import { registerBlockType } from '@wordpress/blocks';
import { useBlockProps, useInnerBlocksProps } from '@wordpress/block-editor';

registerBlockType( 'gutenberg-examples/example-06', {
	// ...

	edit: () => {
		const blockProps = useBlockProps();
		const { children, ...innerBlocksProps } = useInnerBlocksProps( blockProps );

		return (
			<div {...innerBlocksProps}>
    			{ children }
				<!-- Insert any arbitrary html here at the same level as the children -->
			</div>
		);
	},

	// ...
} );

<div>
	<!-- Inner Blocks get inserted here -->
	<!-- The custom html gets rendered on the same level -->
</div>

原文

最終更新日: