WordPressのカスタムブロックで、wp_optionsのデータを使う

それっぽい記事があまり見当たらなかったので簡単に覚書。 やりたいこと WordPressのカスタムブロックを作る APIキーを必要とするリクエストを実行する 複数の記事で利用したいので、APIキーはwp_optionsに […]

広告ここから
広告ここまで

目次

    それっぽい記事があまり見当たらなかったので簡単に覚書。

    やりたいこと

    • WordPressのカスタムブロックを作る
    • APIキーを必要とするリクエストを実行する
    • 複数の記事で利用したいので、APIキーはwp_optionsに保存したい

    実装(Side PHP)

    wp_optionsに保存するための設定系ですこし工夫が必要です。

    register_settingsshow_in_rest=>trueを設定する

    register_settingadd_settings_fieldを使って登録画面と処理を実装することが多いと思います。カスタムブロックでの利用を前提とする場合、register_settingの第三引数でshow_in_rest=>trueを設定しましょう。

    /settingsのAPIからこのデータが取れるようになります。ちなみにこのパスはデフォルトで認証必須なので、管理画面外から取り放題になるというわけではありません。

    register_setting( 'reading', 'example_api_key', array(
        'type' => 'string',
        'sanitize_callback' => 'esc_attr',
        'show_in_rest' => true,
    ) );

    rest_api_initフックでもregister_settingを含む処理を実行する

    多くの場合、register_settingadmin_initフックから実行します。が、今回のケースではWP APIからもデータを参照する関係上rest_api_initフックも利用します。

    add_action( 'admin_init', 'example_init_settings_ui' );
    add_action( 'admin_init', 'example_init_setting_fields' );
    add_action( 'rest_api_init', 'example_init_setting_fields' );

    rest_api_initフックではadd_settings_sectionなどの管理画面表示系の関数を実行するとFatal Errorがおきます。そのため、「フィールド定義関数(register_setting)」+「設定画面定義関数 (add_settings_section / add_settings_field)」の2つに分けておくとよいでしょう。

    実装(Side JS)

    最後にカスタムブロックのJSからの取得です。

    @wordpress/core-datauseEntityPropで取得できます。

    const { useEntityProp } = require('@wordpress/core-data');
    registerBlockType( 'example_block', {
      edit: (props) => {
        const [apiKey] = useEntityProp( 'root', 'site', 'example_api_key' ))
        return (
           <AnyAPIProvider apiKey={apiKey}>
    ...

    あまり調べてないのですが、@types/wordpress__core-dataを入れてTypeScriptで実行しようとすると、useEntityPropが未定義と言われましたので、迷ったら諦めてrequireしちゃうといいと思います。(解決策わかればリプください。)

    注意点: saveには副作用が書けません

    なんとなく「saveする時にfetchして更新すればいいやん」という気持ちになりがちなのですが、カスタムブロックではsaveに指定するコンポーネントにuseXXXXをはじめとする副作用系を書けません。

    以下のようにuseStateを書くだけで落ちるので、諦めましょう。

    ...
      save() {
        useState()
        return (<p>hello</p>)
      }
    }
    
    Invariant Violation: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
    1. You might have mismatching versions of React and the renderer (such as React DOM)
    2. You might be breaking the Rules of Hooks
    3. You might have more than one copy of React in the same app
    See https://fb.me/react-invalid-hook-call for tips about how to debug and fix this problem.

    ブロック内でfetchしたデータは、以下のように取り回すことになります。

    • Edit内データ取得
    • setAttributesでブロックのattributesに保存
    • Save内ではattributesに保存された値を使う

    広告ここから
    広告ここまで
    Home
    Search
    Bookmark