Gutenberg のカスタムブロックでインナーブロックを配置できるようにしたとき、親ブロックからインナーブロックの情報を取得する方法をまとめます。
以下、 @wordpress/create-block を使ってひな形を作成したときのファイル構成を前提に解説します。
インナーブロックを配置できるようにしたときの最小構成
まず、普通に最小構成でブロックを構築するとこんな感じになります。
src/edit.js
import { useBlockProps, useInnerBlocksProps } from '@wordpress/block-editor'; export function Edit() { const blockProps = useBlockProps(); const innerBlocksProps = useInnerBlocksProps( blockProps, {} ); return ( <div { ...innerBlocksProps } /> ); }
やりたいこと
useInnerBlocksProps
を利用すると、簡単お手軽にインナーブロックを配置できるブロックが作れます。
save()
関数側でも <InnerBlocks.Content />
と書くだけでインナーブロックの管理はお任せできます。
しかし、 "お任せできる" というのは言い換えると "ブラックボックスになっていて外から中の状態を知り得ない" ということです。それでは困る場面もあるでしょう。
というわけで親ブロックからインナーブロックの情報を取得してみましょう。
useSelect を使ってインナーブロックの情報を取得する
インナーブロックの情報を取得するために useSelect
を使います。
src/edit.js
import { useBlockProps, useInnerBlocksProps } from '@wordpress/block-editor'; import { useSelect } from '@wordpress/data'; export function Edit({ clientId }) { const innerBlocks = useSelect( select => select( 'core/block-editor' ).getBlocks( clientId ) ); console.log( { innerBlocks } ); const blockProps = useBlockProps(); const innerBlocksProps = useInnerBlocksProps(blockProps, {}); return ( <div { ...innerBlocksProps } /> ); }
useSelect
を使って useSelect( select => select( 'core/block-editor' ).getBlocks( clientId ) )
のように書くとインナーブロックの情報を取得できます。
getBlocks()
メソッドには引数として clientId
を渡す必要があります。 Edit()
のオブジェクト引数から取得できる clientId
をそのまま渡せば大丈夫です。
取得した innerBlocks
を実際に見てみると、以下のようなデータになっています。
[ { "clientId": "0c8bc6d7-4b66-46e7-a1aa-5f7284498655", "name": "core/heading", "isValid": true, "attributes": { "content": "Foo Bar", "level": 1 }, "innerBlocks": [] }, { "clientId": "7e1d6dd0-4152-41a6-98ca-205db0b29a9e", "name": "core/paragraph", "isValid": true, "attributes": { "content": "Hoge Fuga", "dropCap": false }, "innerBlocks": [] } ]
attributes
プロパティを参照することでインナーブロックのコンテンツに設定されているテキストなどが直接手に入ります。
その他 innerBlocks
プロパティを参照すると、「インナーブロックの中のインナーブロック」まで辿っていくこともできます。
withSelect を使ってインナーブロックの情報を取得する
useSelect
の代わりに withSelect
を使ってもインナーブロックの情報を取得できます。
useSelect
を使ったときと理屈は同じです。
src/edit.js
import { useBlockProps, useInnerBlocksProps } from '@wordpress/block-editor'; import { withSelect } from '@wordpress/data'; export const Edit = withSelect( ( select, { clientId } ) => ({ innerBlocks: select( 'core/block-editor' ).getBlocks( clientId ), }))(edit); function edit({ innerBlocks }) { console.log( { innerBlocks } ); const blockProps = useBlockProps(); const innerBlocksProps = useInnerBlocksProps(blockProps, {}); return ( <div { ...innerBlocksProps } /> ); }
withSelect()
の返り値で edit()
関数をデコレートしてあげることで、 edit()
関数のオブジェクト引数に { innerBlocks: [ ... ] }
という形でインナーブロックの情報が引き渡されます。
まとめ
@wordpress/data
の API 、挙動がマジカルすぎて理解が難しい。
私からは以上です。