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()で包みます。