2026年9月22日

2026年9月22日

Interactivity APIの使い方|WordPressのブロックに動きを付ける基本(ディレクティブとストア)

Interactivity APIは、ブロックの公開ページ側に動き(クリックで開く・閉じる、表示の切り替え、データの読み込みなど)を付けるための、WordPress標準の仕組みです。WordPress 6.5で本体に入りました。

HTMLに data-wp- で始まる属性(ディレクティブ)を書き、JavaScriptでは store() に状態と処理を定義します。状態が変わると、ディレクティブに従って表示が自動で更新されます。jQueryでDOMを直接書き換える書き方とは違い、「どの状態のときにどう表示するか」を宣言します。

管理画面のカスタマイザーや、ブロックエディターの中の動きを作るAPIではありません。エディター内の表示は、これまでどおりブロックの edit.js で書きます。

この記事の手順とコードは、2026年10月時点の公式ドキュメントと @wordpress/create-block の雛形に合わせています。

仕組みの全体像

場所 書くもの
render.php(サーバーで作るHTML) ディレクティブ(data-wp-on--click など)で、どの要素が何に反応し、何を表示するかを書く。初期状態もここで渡す
view.js(ブラウザーで動くJavaScript) store() で状態(state)・アクション(actions)・コールバック(callbacks)を定義する
block.json "supports": { "interactivity": true } と "viewScriptModule" で、Interactivity APIを使うことを宣言する

ディレクティブはサーバー側でも処理されます。最初に送られるHTMLが初期状態どおりに描画されるため、JavaScriptが読み込まれる前でも正しい表示になります。

準備

  • WordPress 6.5以上
  • Node.jsとnpm(ブロックのビルドに使う)
  • プラグインを置けるローカルのWordPress環境

手順1: 雛形を作る

wp-content/plugins で、Interactivity API用の公式テンプレートを指定して雛形を作ります。

cd wp-content/plugins
npx @wordpress/create-block@latest toggle-panel --namespace=myplugin --template @wordpress/create-block-interactive-template
cd toggle-panel

src/toggle-panel/ に block.json・render.php・view.js・edit.js などが作られます。block.json には次の設定が入っています。

{
	"supports": {
		"interactivity": true
	},
	"render": "file:./render.php",
	"viewScriptModule": "file:./view.js"
}
  • supports.interactivity: このブロックがInteractivity APIを使うことを示します。サーバー側でディレクティブが処理されるようになります。
  • render: 公開ページのHTMLをPHPで出力します。
  • viewScriptModule: 公開ページで読み込むJavaScriptを、ESモジュールとして読み込みます。

package.json のビルドコマンドには、モジュールを扱うための --experimental-modules がテンプレートで付いています。

手順2: render.phpにディレクティブを書く

ここでは、ボタンで内容を開閉する「折りたたみパネル」を作ります。あわせて、ページ内で開いているパネルの数を表示し、ブロックごとの状態とページ全体の状態の違いを示します。

src/toggle-panel/render.php を次の内容にします。

<?php
/**
 * 公開ページでの表示。$attributes, $content, $block が使える。
 */

$panel_id = wp_unique_id( 'toggle-panel-' );

// グローバルな状態(同じ名前空間のブロックすべてで共有)
wp_interactivity_state(
	'myplugin',
	array(
		'openCount' => 0,
	)
);

// このブロックだけの状態(コンテキスト)
$context = array(
	'isOpen' => false,
);
?>
<div
	<?php echo get_block_wrapper_attributes(); ?>
	data-wp-interactive="myplugin"
	<?php echo wp_interactivity_data_wp_context( $context ); ?>
	data-wp-class--is-open="context.isOpen"
>
	<button
		type="button"
		data-wp-on--click="actions.toggle"
		data-wp-bind--aria-expanded="context.isOpen"
		aria-controls="<?php echo esc_attr( $panel_id ); ?>"
	>
		<span data-wp-bind--hidden="context.isOpen"><?php esc_html_e( '詳しく見る', 'toggle-panel' ); ?></span>
		<span data-wp-bind--hidden="!context.isOpen"><?php esc_html_e( '閉じる', 'toggle-panel' ); ?></span>
	</button>

	<div id="<?php echo esc_attr( $panel_id ); ?>" data-wp-bind--hidden="!context.isOpen">
		<p><?php esc_html_e( 'ここに折りたたむ内容が入ります。', 'toggle-panel' ); ?></p>
	</div>

	<p>
		<?php esc_html_e( 'このページで開いているパネルの数:', 'toggle-panel' ); ?>
		<span data-wp-text="state.openCount"></span>
	</p>
</div>
  • data-wp-interactive="myplugin": この要素とその中が、名前空間 myplugin のストアの対象になります。view.js の store() と同じ名前にします。
  • wp_interactivity_data_wp_context(): 配列を data-wp-context 属性として正しく出力する関数です。コンテキストは、その要素の中だけで使える状態で、ブロックを2つ置けばそれぞれ別の値を持ちます。
  • wp_interactivity_state(): 名前空間全体で共有する状態(グローバルな状態)の初期値をサーバーで決めます。ここで渡した値は、ブラウザー側の state に引き継がれます。
  • !context.isOpen のように ! を付けると、真偽を反転します。

手順3: view.jsにストアを書く

src/toggle-panel/view.js を次の内容にします。

import { store, getContext } from '@wordpress/interactivity';

const { state } = store( 'myplugin', {
	actions: {
		toggle() {
			const context = getContext();
			context.isOpen = ! context.isOpen;
			state.openCount += context.isOpen ? 1 : -1;
		},
	},
} );
  • getContext() は、アクションが呼ばれた要素のコンテキストを返します。押されたボタンのブロックの isOpen だけが切り替わります。
  • state.openCount はページ全体で共有されるので、どのパネルを開閉しても、すべてのブロックの「開いているパネルの数」が同時に更新されます。
  • 値を書き換えるだけで、hidden 属性・aria-expanded・is-open クラス・数の表示が自動で更新されます。DOMを直接操作するコードは書きません。

手順4: ビルドして確かめる

npm run build
wp plugin activate toggle-panel

WP-CLIを使わない場合は、管理画面の「プラグイン」で有効化します。投稿にブロックを2つ追加して公開ページを開き、ボタンでそれぞれのパネルが開閉すること、開いている数が変わることを確かめます。開発中は npm start にすると、保存するたびにビルドされます。

エディターの中では、雛形の edit.js が出す仮の文が表示されます。Interactivity APIの動きは公開ページでだけ働きます。

よく使うディレクティブ

ディレクティブ 働き 例
data-wp-interactive 名前空間を決め、その範囲を対象にする data-wp-interactive="myplugin"
data-wp-context その要素の中だけの状態(JSON) data-wp-context='{ "isOpen": false }'
data-wp-on--イベント名 イベントでアクションを呼ぶ data-wp-on--click="actions.toggle"
data-wp-on-window--イベント名・data-wp-on-document--イベント名 window・document のイベントを受ける data-wp-on-document--keydown="actions.onKeydown"
data-wp-bind--属性名 値に応じてHTMLの属性を付け外しする data-wp-bind--hidden="!context.isOpen"
data-wp-class--クラス名 真偽に応じてクラスを付け外しする data-wp-class--is-open="context.isOpen"
data-wp-style--プロパティ名 インラインスタイルを設定する data-wp-style--color="state.color"
data-wp-text 要素の文字を値で置き換える data-wp-text="state.openCount"
data-wp-init 要素が作られたときに1回だけコールバックを呼ぶ data-wp-init="callbacks.setup"
data-wp-watch 作られたときと、使っている値が変わるたびにコールバックを呼ぶ data-wp-watch="callbacks.logIsOpen"
data-wp-each--名前 配列の要素ごとに <template> の中身を繰り返す data-wp-each--item="context.items"

状態の種類と使い分け

種類 定義する場所 使う場面
コンテキスト(context) data-wp-context(PHPでは wp_interactivity_data_wp_context()) ブロックや要素ごとに違う値。開閉状態など
グローバルな状態(state) wp_interactivity_state() と store() の state ページ全体で共有する値。カートの個数、表示テーマなど
派生した状態 store() の state に書くゲッター(get 名前() { ... }) ほかの値から計算できる値
設定値(config) wp_interactivity_config()(ブラウザーでは getConfig()) 変わらない設定値。REST APIのURLなど

派生した状態(ゲッター)はブラウザーで計算されます。サーバーで描画する最初のHTMLにもその値を出したい場合は、同じ名前の値を wp_interactivity_state() でも渡します。雛形の render.php の themeText がその例です。

イベントを同期的に扱うときはwithSyncEvent

event.preventDefault()・event.stopPropagation()・event.currentTarget を使うアクションは、WordPress 6.8以降、withSyncEvent() で包みます。Interactivity APIはアクションを非同期に実行するため、包まないとイベントの処理が間に合わないことがあり、非推奨の警告が出ます。

import { store, withSyncEvent } from '@wordpress/interactivity';

store( 'myplugin', {
	actions: {
		// event.preventDefault() を使うので withSyncEvent で包む
		openWithoutNavigation: withSyncEvent( ( event ) => {
			event.preventDefault();
			// ここでパネルを開く処理などを行う
		} ),
	},
} );

非同期の処理(fetch など)を書くアクションは、async/await ではなくジェネレーター関数と yield で書くよう案内されています。REST APIから投稿を読み込む例は、WordPressのInteractivity APIでカスタムブロックを作る|REST APIからデータを取得する例で説明しています。

うまく動かないとき

症状 確かめること
ボタンを押しても何も起きない data-wp-interactive と store() の名前空間が一致しているか。npm run build 後の build/ があるか
最初の表示で、閉じているはずの内容が見える block.json に "supports": { "interactivity": true } があるか(無いとサーバーでディレクティブが処理されない)
コンソールに @wordpress/interactivity の読み込みエラー WordPressが6.5以上か。block.json が viewScript ではなく viewScriptModule になっているか
preventDefault などで警告が出る アクションを withSyncEvent() で包んだか
ブロックを2つ置くと両方が一緒に開閉する 開閉状態を state(全体で共有)に入れていないか。ブロックごとの値は context に入れる

まとめ

  • Interactivity APIは、ブロックの公開ページ側の動きを作るWordPress 6.5以降の標準の仕組みです。管理画面やエディター内の動きを作るものではありません。
  • render.php にディレクティブを書き、view.js の store() に状態とアクションを定義します。状態を書き換えると表示が自動で更新されます。
  • ブロックごとの値はコンテキスト、ページ全体で共有する値は wp_interactivity_state() と state に置きます。
  • イベントを同期的に扱うアクションは withSyncEvent() で包みます。

お気軽にご相談ください

お見積りへ お問い合わせへ
▲