WordPressのブロック開発メモ その4ー2 ダイナミックブロック

今回はsaveコンポネントを破棄し、サーバーサイドでレンダリングする方法です。

saveを削除

saveではフロント表示用のコンポーネントを定義していました。
これをサーバーサイドでレンダリングすることが出来ます。

そうなるとsaveは不要になるので除外します。
index.tsregisterBlockType()からsaveを変更します。

import { BlockConfiguration, registerBlockType } from '@wordpress/blocks';

import Edit from './edit';
import save from './save';

import metadata from './block.json';
import KurageExampleBlockProps from './props';

import './style.scss';

const blockConf: BlockConfiguration<KurageExampleBlockProps> =
{
    attributes: {},
    title: metadata.title,
    category: metadata.category,
    edit: Edit,
    save: props => null,
};

registerBlockType(metadata.name, blockConf);
save: props => null,

これまでのsaveコンポーネントを一旦無視して変更します。
IDEにsaveが使われてないって文句をいわれる時はimportをコメントアウトしてください。

プレビューを見ると何も表示されなくなってます。

nullを返したんだから当然です。

サーバーサイドの変更

次にPHP側の変更です。
kurage-worker.phpを変更します。

function create_block_kurage_worker_block_init() {
    register_block_type(
        __DIR__ . '/build',
        [
            'render_callback' => function($attr, $content)
            {
                return 'Hello Dynamic Kurage!';
            }
        ]
    );
}
add_action( 'init', 'create_block_kurage_worker_block_init' );

register_block_type()の第二引数はオプション(連想配列)です。
render_callbackにコールバック関数を指定し、その戻り値がsaveの変わりに描画されます。

この時、コールバックの$contentは本来saveが描画するはずのHTMLのようです。
もしeditを変更してなければ以下のようなHTMLが送られてきます。

saveが以下の場合なら、

export default (props: BlockSaveProps<KurageExampleBlockProps>) =>
{
    return (
        <div { ...useBlockProps.save() }>
            <p>Hello Kurage !!</p>
        </div>
    );
}

$contentで受け取る値はこうなります。

<div class="wp-block-create-block-kurage-worker"><p>Hello Kurage !!</p></div>

$attrは属性を取得します。

属性

属性を使っていきます。

block.jsonattributesを追加。

{
    "$schema": "https://schemas.wp.org/trunk/block.json",
    "apiVersion": 2,
    "name": "create-block/kurage-worker",
    "version": "0.1.0",
    "title": "Kurage Worker",
    "category": "widgets",
    "icon": "smiley",
    "description": "Example block scaffolded with Create Block tool.",
    "supports": {
        "html": false
    },
    "attributes": {
        "message": {
            "type": "string",
            "default": ""
        }
    },
    "textdomain": "kurage-worker",
    "editorScript": "file:./index.js",
    "editorStyle": "file:./index.css",
    "style": "file:./style-index.css"
}

edit.tsxmessage属性を編集出来るよう設定。

import React from 'react';
import { useBlockProps } from '@wordpress/block-editor';
import { BlockEditProps } from '@wordpress/blocks';

import KurageExampleBlockProps from './props';
import './editor.scss';
import { TextControl } from '@wordpress/components';

export default (props: BlockEditProps<KurageExampleBlockProps>) =>
{
    const cc = useBlockProps();
    const { message } = props.attributes;
    const { setAttributes } = props;

    return (
        <div {...cc}>

            メッセージ:
            <TextControl
                value={message}
                onChange={v => setAttributes({ message: v })}
                />

        </div>
    );
}

index.tsxpropsも編集。
propsの型にmessageの追加と、オプションにattributesの追加を行う。

export default interface KurageExampleBlockProps
{
     message: string;
}
import { BlockConfiguration, registerBlockType } from '@wordpress/blocks';

import Edit from './edit';
import save from './save';

import metadata from './block.json';
import KurageExampleBlockProps from './props';

import './style.scss';

// 第二引数の型、ジェネリックの引数にはpropsの型を指定
const blockConf: BlockConfiguration<KurageExampleBlockProps> =
{
    attributes: metadata.attributes as any,
    title: metadata.title,
    category: metadata.category,
    edit: Edit,
    save //: props => null,
};

registerBlockType(metadata.name, blockConf);

今回attributesの設定をblock.jsonの方に書いたのでそれを引っ張ってくる。

kurage-worker.php

function create_block_kurage_worker_block_init() {
    register_block_type(
        __DIR__ . '/build',
        [
            'render_callback' => function($attr, $content)
            {
                return "Message: {$attr["message"]}";
            }
        ]
    );
}

PHP側も変更。
$attrからmessage属性を取得出来ます。

結果を見てみましょう。

編集ページ

プレビュー

属性を利用し、例えばPostのIDを渡すようにしてサーバー上でその投稿をレンダリングしたり出来ます。
the_post()などその場で出力してしまうような関数はバッファリングしてから返すように工夫する必要があります。

編集側でもサーバーサイドレンダリング

さっきはフロント(プレビュー)側での表示でした。
今度は編集側でサーバーサイドレンダリングする方法です。
実はそれ用のコンポーネントが存在します。

その名もServerSideRenderです。

ServerSideRenderを使用するには以下をインストールします。

 npm install --save @wordpress/server-side-render

edit.tsx

import React from 'react';
import { useBlockProps } from '@wordpress/block-editor';
import { BlockEditProps } from '@wordpress/blocks';
import ServerSideRender from '@wordpress/server-side-render';

import KurageExampleBlockProps from './props';
import './editor.scss';
import { TextControl } from '@wordpress/components';

export default (props: BlockEditProps<KurageExampleBlockProps>) =>
{
    const cc = useBlockProps();
    const { message } = props.attributes;
    const { setAttributes } = props;

    return (
        <div {...cc}>

            メッセージ:
            <TextControl
                value={message}
                onChange={v => setAttributes({ message: v })}
                />

            <p>↓プレビュー</p>

            <ServerSideRender
                block="create-block/kurage-worker"
                attributes={ {message} }
                />

        </div>
    );
}

入力するとサーバーサイドレンダリングされた結果が表示されます。
連続で入力すると頻繁にサーバー(render_callback)にアクセスがあります。

読み込み中の確認

気づきにくい読み込み中の処理は既に備わってます。

kurage-worker.phpの一部を変更します。

function create_block_kurage_worker_block_init() {
    register_block_type(
        __DIR__ . '/build',
        [
            'render_callback' => function($attr, $content)
            {
                sleep(3);
                return "Message: {$attr["message"]}";
            }
        ]
    );
}
add_action( 'init', 'create_block_kurage_worker_block_init' );

sleep(3)でサーバーサイドでの処理を3秒間止めてみました。

デフォルトでの読み込み中の処理です。
Spinnerが表示されていることが確認出来ます。

ServerSideRenderLoadingResponsePlaceholderを使って上書出来るのですが興味ある方はソースコードを見て参考にしてみてください。

https://github.dev/WordPress/gutenberg/blob/trunk/packages/server-side-render/src/server-side-render.js

BlockEditor certificate css DataGrid Docker Gutenberg Hyper-V iframe MUI openssl PHP React ReduxToolkit REST ubuntu WordPress オレオレ認証局 フレームワーク