メインコンテンツへスキップ
How Can We Help?

Search for answers or browse our knowledge base.

Documentation | Demos | Support

< All Topics
Print

プラグインページに WordPress React コンポーネントを使用する方法

How to use WordPress React components for plugin pages のページの翻訳した内容となります。

ここから========

最新で動的な投稿およびサイトエディターと比較して、ほとんどの WordPress 管理領域が静的で時代遅れに見えると感じたことがあるのは、あなただけではありません。

しかし、良いニュースがあります。これは変わりつつあります。 WordPress がフェーズ 3: コラボレーションに入り、全体的な管理エクスペリエンスを向上させ、新しいビジュアル言語を全体に統合するための継続的な取り組みが行われています。

WordPress のエコシステムも変化しています。 多くの有名なプラグインの設定ページが更新されました。 ユーザーエクスペリエンスを向上させ、新機能の導入を迅速化するために、ユーザーインターフェイスに React を選択する開発者が増えています。

あなたも同じことをしたい場合はどうすればよいですか?

この記事では、WordPress React コンポーネントを利用してプラグイン用の React ベースの設定ページを作成する方法を説明します。

どのようなものを作るつもりですか?

この記事では、フロントエンドのヘッダーの上にアナウンスバーを表示するプラグインを構築します。

これには、メッセージをカスタマイズしたり、バーの表示を切り替えたり、サイズを調整したりできる設定ページが含まれています。

最終結果の概要は次のとおりです。

(翻訳元のページの動画を確認してください。)

モジュラーアーキテクチャの力

投稿およびサイトの編集者と連携すると、統一されたシステムの印象が与えられます。 ただし、これらは独立したコンポーネントとパッケージのオーケストレーションの産物です。

Gutenberg プロジェクトは当初から、パッケージを疎結合または完全に分離することを受け入れていました。 このモジュラーアーキテクチャを使用すると、さまざまなインターフェイスやアプリケーションを作成することができます。

これらのパッケージを使用して設定ページを作成しますが、再利用性と多用途性を考慮すると、WordPress ベース以外のプロジェクトでも使用できます。

前提知識と前提条件

この記事は、React についてある程度の知識があることを前提としています。 基本的なカスタムブロック(英語版)を開発したことがある場合は、スキルと概念が非常に応用可能であるため、特に使いやすくなります。

コーディングを進めたい場合は、次のスターターファイルを作成します。

/plugins/unadorned-announcement-bar/
├── index.php
├── package.json
└── src/
    ├── index.js
    └── index.scss

JavaScript ビルドステップ用の wp-scripts も必要です。 セットアップと使用に関する段階的なチュートリアルについては、「wp-scripts の開始(英語版)」を参照してください。

すでに慣れている場合は、開始するために package.json に必要なものを以下に示します。

{
    "devDependencies": {
        "@wordpress/scripts": "^27.0.0"
    },
    "scripts": {
        "build": "wp-scripts build",
        "start": "wp-scripts start"
    }
}

基礎部分を作成

最初の手順は、「従来の」カスタム設定ページでプラグインを作成する場合と変わりません。

このセクションは短く要点を絞ったものになっています。 いずれかの手順についてさらに詳しい情報が必要な場合は、「プラグインの基本」ページを参照してください。

メニューと設定ページのセットアップ

まず、開始するには、最小限必要なプラグイン ヘッダー コメントを index.php ファイルに追加し、次に [設定] メニューの下にサブメニューを登録します。

<?php
/**
 * Plugin Name: Unadorned Announcement Bar
 */

function unadorned_announcement_bar_settings_page() {
    add_options_page(
        __( 'Unadorned Announcement Bar', 'unadorned-announcement-bar' ),
        __( 'Unadorned Announcement Bar', 'unadorned-announcement-bar' ),
        'manage_options',
        'unadorned-announcement-bar',
        'unadorned_announcement_bar_settings_page_html'
    );
}

add_action( 'admin_menu', 'unadorned_announcement_bar_settings_page' );

次に、同じ PHP ファイルにコールバック関数を追加します。

function unadorned_announcement_bar_settings_page_html() {
    printf(
        '<div class="wrap" id="unadorned-announcement-bar-settings">%s</div>',
        esc_html__( 'Loading…', 'unadorned-announcement-bar' )
    );
}

一意の ID を持つ HTML 要素を出力するだけで十分です。 この id を使用して、JavaScript で要素をターゲットにします。 「読み込み中…(loading)」メッセージは、JavaScript 部分が初期化されると置き換えられます。

設定ページにアクセスするには、「設定」に移動し、次に「Unadorned Announcement Bar(飾りのないアナウンスバー)」に移動します。

React 用の JavaScript をキューに入れる

React ベースの設定ページを構築している場合、必要な JavaScript ファイルをキューに入れる必要があります。 これを行うには、次のコードを index.php ファイルに追加します。

function unadorned_announcement_bar_settings_page_enqueue_style_script( $admin_page ) {
    if ( 'settings_page_unadorned-announcement-bar' !== $admin_page ) {
        return;
    }

    $asset_file = plugin_dir_path( __FILE__ ) . 'build/index.asset.php';

    if ( ! file_exists( $asset_file ) ) {
        return;
    }

    $asset = include $asset_file;

    wp_enqueue_script(
        'unadorned-announcement-bar-script',
        plugins_url( 'build/index.js', __FILE__ ),
        $asset['dependencies'],
        $asset['version'],
        array(
            'in_footer' => true,
        )
    );
}

add_action( 'admin_enqueue_scripts', 'unadorned_announcement_bar_settings_page_enqueue_style_script' );

JavaScript が設定ページにのみ読み込まれるようにすることで、ベストプラクティスに従っていることになります。また、依存関係とバージョンを動的に設定しているため、それらを更新する必要はありません。

ビルドフォルダーとその内容は、JavaScript が wp-scriptsコンパイルされるときに作成されます。

React 設定ページのキックスタート

前の手順が完了したら、いよいよ React コードを作成します。

すべての作業を完了したことを確認するには、プレースホルダー コンポーネントのレンダリングなどの基本的な作業から始めます。

このコードを src/index.js ファイルに追加します。

import domReady from '@wordpress/dom-ready';
import { createRoot } from '@wordpress/element';

const SettingsPage = () => {
    return <div>Placeholder for settings page</div>;
};

domReady( () => {
    const root = createRoot(
        document.getElementById( 'unadorned-announcement-bar-settings' )
    );

    root.render( <SettingsPage /> );
} );

npm install {package} を使用して、前述のパッケージを忘れずにインストールしてください。 新しいパッケージへの参照が見つかった場合は、それらもインストールしてください。 まだ開始していない場合は、wp-scripts ビルドプロセスを開始します。

domReady を使用すると、DOM を操作できる状態になります。 コールバック内で、createRoot を使用して、指定した要素の DOM の管理を引き継ぐように React に指示します。 次に、SettingsPage コンポーネントをレンダリングします。

これらの手順は、すべての React アプリケーションに共通です。 投稿エディタとサイト エディタが初期化されるときに、非常に似たようなことが起こります。

設定ページを更新すると、プレースホルダーメッセージが表示されるはずです。

WordPress などで再利用可能な UI 要素

@wordpress/components は基礎パッケージの 1 つです。 ブロックエディターとサイトエディターに使用される共通の UI 要素が含まれているため、頻繁に使用されますが、他の場所でも使用できるほど汎用的です。

利用可能なコンポーネントの概要については、WordPress Storybook を参照してください。 Storybook を使用すると、個々のコンポーネント、そのコントロール、オプション、設定を個別に参照できます。 コントロールと引数を変更すると、その変更をすぐに確認できます。

利用可能なコンポーネントは多岐にわたります。WordPress のより多くの領域がオーバーホールされるにつれて、このリストはさらに拡大することが予想されます

Storybook では、ビジュアルコンポーネントとしても存在する React コードコンポーネントを操作します。 これらは、コードで利用可能で実装されているものを正確に反映しています。

ビジュアルコンポーネント

ビジュアルコンポーネントは、Figma でモックアップを作成したり、コードを記述する前の早い段階でアイデアを検討したりするために使用できる、再利用可能な UI の一部です。

利用可能なビジュアルコンポーネントから選択するだけで、プラグインのモックアップを作成できます。

WordPress のデザインとの一貫性を保ちたい場合は、いくつかのコントロールを組み合わせて配置し、ボタンとタイトルを追加する必要があります。

設定ページのUIの構築

パネル

モックアップに基づいて、設定は 2 つのセクションにグループ化されており、[外観] セクションはデフォルトで非表示になっています。

Panel コンポーネントは、オプションのヘッダーを持つコンテナーを作成し、折りたたむことができるPanelBody コンポーネントを受け入れるため、このユースケースに最適です。

これを統合するには、まず src/index.js ファイルの先頭にある依存関係をインポートする必要があります。

import { __ } from '@wordpress/i18n';
import { Panel, PanelBody, PanelRow } from '@wordpress/components';

import ステートメントは常にファイルの先頭に置かれることに注意してください。 繰り返しを避けるため、この詳細については今後は明示的に言及しません。

次に、SettingsPage コンポーネントを変更します。 現時点では、最終的にコントロールが次のようになるプレースホルダーメッセージを使用します。

const SettingsPage = () => {
    return (
        <Panel>
            <PanelBody>
                <PanelRow>
                    <div>Placeholder for message control</div>
                </PanelRow>
                <PanelRow>
                    <div>Placeholder for display control</div>
                </PanelRow>
            </PanelBody>
            <PanelBody
                title={ __( 'Appearance', 'unadorned-announcement-bar' ) }
                initialOpen={ false }
            >
                <PanelRow>
                    <div>Placeholder for size control</div>
                </PanelRow>
            </PanelBody>
        </Panel>
   );
};

PanelPanelBodyPanelRow コンポーネントは常に一緒に使用されます。 これらおよび後続のコンポーネントにはさまざまなオプションが用意されていますが、そのすべてがこのプロジェクトに必要なわけではありません。 Storybook を探索すると、さらなる可能性を発見できます。

この時点で、設定ページを更新すると、レンダリングされたコンポーネントが表示されるはずです。

コンポーネントのスタイルを含む

現時点では、状況はあまり良くないようです。 これは、デフォルトではコンポーネントにスタイルが設定されていないため、CSS を含める必要があるためです。

これは、wp-components スタイルシートをキューに入れることで解決できます。 index.php ファイル内の現在の関数を修正します。

function unadorned_announcement_bar_settings_page_enqueue_style_script( $admin_page ) {
    // ...

    wp_enqueue_style( 'wp-components' );
}

これで、設定ページが WordPress っぽくなるはずです。

コントロールの状態を管理する

このプラグインには複雑な状態管理は必要ありません。 追跡するコントロールが 3 つと値が 3 つだけなので、useState の 3 つのインスタンスといくつかのデフォルト値から始めることができます。

状態をプレゼンテーション層から分離するには、カスタムフックでカプセル化するのが最善です。 ここから、特に記載がない限り、すべてのコードを src/index.js ファイルに追加します。

import { useState } from '@wordpress/element';

const useSettings = () => {
    const [ message, setMessage ] = useState('Hello, World!');
    const [ display, setDisplay ] = useState(true);
    const [ size, setSize ] = useState('medium');
    
    return {
        message,
        setMessage,
        display,
        setDisplay,
        size,
        setSize,
    };
};

現在のコードはわずか数行ですが、データベースにデータを保存したり、データベースからデータをロードしたりすると、コードは必然的に複雑になります。 カスタム フックと状態管理の中心的な場所の利点は、すぐに明らかになるでしょう。 乞うご期待。

SettingsPage コンポーネントの状態変数とセッター関数にアクセスするには、 useSettings を呼び出し、返されたオブジェクトを構造解除します。

const SettingsPage = () => {
    const {
        message,
        setMessage,
        display,
        setDisplay,
        size,
        setSize,
    } = useSettings();

    // ...
};

メッセージコントロール

アナウンス バー メッセージに長いテキストを許可するには、TextareaControl コンポーネントを使用するのが間違いありません。

整理整頓するには、別のコンポーネントでラップします。

import { TextareaControl } from '@wordpress/components';

const MessageControl = ( { value, onChange } ) => {
    return (
        <TextareaControl
            label={ __( 'Message', 'unadorned-announcement-bar' ) }
            value={ value }
            onChange={ onChange }
            __nextHasNoMarginBottom
        />
    );
};

WordPress が進化するにつれて、既存のコンポーネントのスタイルを調整することが必要になる場合があります。 新しいスタイルが導入されると、__next という接頭辞が付いた機能フラグプロパティの後ろに置かれます。 これにより、サードパーティが必要な調整を行うための猶予期間が提供されます。

プレースホルダーを作成したら、次のステップはプレースホルダーを MessageControl コンポーネントに置き換えることです。 message 定数を値として使用し、onChange ハンドラーでそのセッター関数を使用します。

const SettingsPage = () => {
    const {
        message,
        setMessage,
        // ...
    } = useSettings();
    
    return (
        <Panel>
            <PanelBody>
                <PanelRow>
                    <MessageControl
                        value={ message }
                        onChange={ ( value ) => setMessage( value ) }
                    />
                </PanelRow>
                <PanelRow></PanelRow>
            </PanelBody>
            <PanelBody></PanelBody>
        </Panel>
    );
};

これらすべての作業により、最初のコントロールが機能し、メッセージを更新できるようになります。

ディスプレイコントロール

アナウンス バーの表示を切り替えるには、オン/オフ スイッチが必要です。 ToggleControl コンポーネントを選択します。

一貫性を維持するには、前のセクションで示したのと同じアプローチに従ってください。 まず、コントロール用に別のコンポーネントを作成します。

import { ToggleControl } from '@wordpress/components';

const DisplayControl = ( { value, onChange } ) => {
    return (
        <ToggleControl
            label={ __( 'Display', 'unadorned-announcement-bar' ) }
            checked={ value }
            onChange={ onChange }
            __nextHasNoMarginBottom
        />
    );
};

次に、使用していたプレースホルダーを DisplayControl コンポーネントに置き換え、onChange ハンドラーに対応する定数とセッター関数を使用します。

const SettingsPage = () => {
    const {
        // ...
        display,
        setDisplay,
        // ...
    } = useSettings();

    return (
        <Panel>
            <PanelBody>
                <PanelRow></PanelRow>
                <PanelRow>
                    <DisplayControl
                        value={ display }
                        onChange={ ( value ) => setDisplay( value ) }
                    />
                </PanelRow>
            </PanelBody>
            <PanelBody></PanelBody>
        </Panel>
    );
};

サイズコントロール

サイズコントロールには、いくつかの異なるコンポーネントから選択できますが、最も適しているのは多用途の FontSizePicker コンポーネントです。

前のコントロールと同様に、別のコンポーネントを作成します。 ここでの唯一の違いは、可能なオプションのリストを定義する必要があることです。

import { FontSizePicker } from '@wordpress/components';

const SizeControl = ( { value, onChange } ) => {
    return (
        <FontSizePicker
            fontSizes={ [
                {
                    name: __( 'Small', 'unadorned-announcement-bar' ),
                    size: 'small',
                    slug: 'small',
                },
                {
                    name: __( 'Medium', 'unadorned-announcement-bar' ),
                    size: 'medium',
                    slug: 'medium',
                },
                {
                    name: __( 'Large', 'unadorned-announcement-bar' ),
                    size: 'large',
                    slug: 'large',
                },
                {
                    name: __( 'Extra Large', 'unadorned-announcement-bar' ),
                    size: 'x-large',
                    slug: 'x-large',
                },
            ] }
            value={ value }
            onChange={ onChange }
            disableCustomFontSizes={ true }
            __nextHasNoMarginBottom
        />
    );
};

デフォルトでは、事前定義された値のリスト以外の任意のサイズを選択できますが、「飾らない」状態を維持するには、disableCustomFontSizes プロパティを使用してこの可能性を無効にします。

最後に、プレースホルダーテキストを実際のコンポーネントに置き換え、valueonChange プロパティを構成します。

const SettingsPage = () => {
    const {
        // ...
        size,
        setSize,
    } = useSettings();

    return (
        <Panel>
            <PanelBody></PanelBody>
            <PanelBody
                title={ __( 'Appearance', 'unadorned-announcement-bar' ) }
                initialOpen={ false }
>        
                <PanelRow>
                    <SizeControl
                        value={ size }
                        onChange={ ( value ) => setSize( value ) }
                    />
                </PanelRow>
            </PanelBody>
        </Panel>
    );
};

この時点で、3 つのコントロールがすべて機能するようになり、作業の半分は終了です。 設定ページは次のようになります。

保存ボタン

設定ページの基本を完了するには、さらに 2 つのコンポーネントを追加する必要があります。

何よりもまず、保存用の Button コンポーネントが必要です。 前に行ったように、そのラッパー コンポーネントを作成します。

import { Button } from '@wordpress/components';

const SaveButton = ( { onClick } ) => {
    return (
        <Button variant="primary" onClick={ onClick } __next40pxDefaultSize>
            { __( 'Save', 'unadorned-announcement-bar' ) }
        </Button>
    );
};

次に、Panel コンポーネントの直後に SaveButton コンポーネントを追加します。

const SettingsPage = () => {
    // ...

    return (
        <>
            <Panel></Panel>
            <SaveButton onClick={ () => {} } />
        </>
    );
};

クリックしても、今のところ特に何もしなくても問題ありません。 保存機能はすぐに追加します。

React では 1 つのコンポーネントしか返せないため、2 つのコンポーネントをフラグメント (< > < / > の間) でラップすることを忘れないでください。

実験的な見出し

Storybook で、一部のコンポーネントが実験的としてマークされていることに気づいたかもしれません。

これらは WordPress の下位互換性保証が適用されないため、実験的と呼ばれます。 あるバージョンから別のバージョンに変更される可能性があり、コードが壊れる可能性があります。

使用には注意が必要ですが、試してみるには、プレーンな h1 タグの代わりに、タイトルに __experimentalHeading コンポーネントを使用できます。

import {
    // eslint-disable-next-line @wordpress/no-unsafe-wp-apis
    __experimentalHeading as Heading,
} from '@wordpress/components';

const SettingsTitle = () => {
    return (
        <Heading level={ 1 }>
            { __( 'Unadorned Announcement Bar', 'unadorned-announcement-bar' ) }
        </Heading>
    );
};

wp-scripts を使用してコードをリントすると、実験的なコンポーネントが使用されている場合に警告がトリガーされます。 eslint-disable-next-line を使用して、何をしているかを知っていることを示すことができます。

今回は、Panel コンポーネントの前にコンポーネントを追加して、ページの上部にレンダリングします。

const SettingsPage = () => {
    // ...

    return (
        <>
            <SettingsTitle />
            <Panel></Panel>
            <SaveButton />
        </>
    );
};

設定の永続化とロード

通常の WordPress 設定ページでは、変更を加えて保存すると、フォームが送信され、ページがリロードされます。

このアプローチは、React の動的インタラクションモデルと一致しません。 ブロックおよびサイトエディターで何かが読み込まれたり保存されたりすると、多くの REST API リクエストがバックグラウンドで実行されている間、それがシームレスに行われます。 同様に、REST API を使用して設定を読み込み、保存します。

コントロールの状態を個別の単一の値としてオプションテーブルに保存することもできますが、それぞれに対して不必要に新しいレコードが作成されてしまいます。 このプラグインの場合は、他のオプション、つまり単一のキーの下に値の配列として保存するオプションを選択する必要があります。

デフォルトとスキーマの定義

get_option( 'unadorned_payment_bar' ) を呼び出したときに常に期待値を取得するには、そのデフォルトを定義する必要があります。

また、スキーマも厳密に定義すると、REST API を使用する際の検証について心配する必要がなく、WordPress が処理します。

register_setting 関数を使用して両方を実現します。 次のコードを index.php ファイルに配置します。

function unadorned_announcement_bar_settings() {
    $default = array(
        'message' => __( 'Hello, World!', 'unadorned-announcement-bar' ),
        'display' => true,
        'size'    => 'medium',
    );
    $schema  = array(
        'type'       => 'object',
        'properties' => array(
            'message' => array(
                'type' => 'string',
            ),
            'display' => array(
                'type' => 'boolean',
            ),
            'size'    => array(
                'type' => 'string',
                'enum' => array(
                    'small',
                    'medium',
                    'large',
                    'x-large',
                ),
            ),
        ),
    );

    register_setting(
        'options',
        'unadorned_announcement_bar',
        array(
            'type'         => 'object',
            'default'      => $default,
            'show_in_rest' => array(
                'schema' => $schema,
            ),
        )
    );
}

add_action( 'init', 'unadorned_announcement_bar_settings' );

設定を読み込む

設定ページに到達したら、設定を読み込みます。

コンポーネントがマウントされた後にアクションをトリガーしたい場合は、いつでも useEffect フックを使用できます。 この場合、apiFetch を使用してサイト設定エンドポイントにリクエストを送信し、保存された設定を読み込んで使用します。

これはすべて状態管理に関連しているため、src/index.js ファイルにある useSettings カスタムフックをそれに応じて変更します。

import apiFetch from '@wordpress/api-fetch';
import { useEffect } from '@wordpress/element';

const useSettings = () => {
    const [ message, setMessage ] = useState();
    const [ display, setDisplay ] = useState();
    const [ size, setSize ] = useState();

    useEffect( () => {
        apiFetch( { path: '/wp/v2/settings' } ).then( ( settings ) => {
            setMessage( settings.unadorned_announcement_bar.message );
            setDisplay( settings.unadorned_announcement_bar.display );
            setSize( settings.unadorned_announcement_bar.size );
        } );
    }, [] );
    
    // ...
};

register_setting で定義されたデフォルトは、エンドポイントによって使用可能になります。 このため、useState 呼び出しにデフォルト値を設定する必要はなくなりました。 エンドポイントからデータが返されたら、setter 関数を使用して状態を更新します。 このプロセスはほぼ瞬時に行われます。

設定を保存する

データの読み込みを処理した方法と同じように、サイト設定エンドポイントを使用して設定を保持できます。

今回は、REST API 呼び出しはページの読み込み時ではなく、保存ボタンをクリックしたときに発生します。 したがって、まず、useSettings フック内の関数に apiFetch をカプセル化します。

const useSettings = () => {
    // ...

    const saveSettings = () => {
        apiFetch( {
            path: '/wp/v2/settings',
            method: 'POST',
            data: {
                unadorned_announcement_bar: {
                    message,
                    display,
                    size,
                },
            },
        } );
    };

    return {
        // ...
        saveSettings,
    };
};

次に、エクスポートされた saveSettings 関数を SaveButton コンポーネントの onClick のハンドラーとして使用できます。

const SettingsPage = () => {
    const {
        // ...
        saveSettings,
    } = useSettings();

    return (
        <>
            <SettingsTitle/>
            <Panel></Panel>
            <SaveButton onClick={ saveSettings } />
        </>
    );
};

ここで、「保存」ボタンを押すと、変更を保存できます。 設定ページを更新すると、保存された設定がロードされます。

不足しているものはあといくつかありますが、そのうちの 1 つはフロントエンド機能です。

フロントエンドにアナウンスバーを表示する

アナウンス バーを表示する最も簡単な方法は、body タグの直後にアナウンス バーを出力することです。

wp_body_open フックを使用できます。これは、今日ではどのテーマにも存在することが期待されています。 次のコードを index.php ファイルに追加します。

function unadorned_announcement_bar_front_page() {
    $options = get_option( 'unadorned_announcement_bar' );

    if ( ! $options['display'] ) {
        return;
    }

    printf(
        '<div>%s</div>',
        esc_html( $options['message'] )
    );
}

add_action( 'wp_body_open', 'unadorned_announcement_bar_front_page' );

アナウンスバーに必要なスタイルは最小限であるため、CSS をインライン化するだけで済みます。 作成したばかりの関数をそれに応じて更新します。

function unadorned_announcement_bar_front_page() {
    // ...

    printf(
        '<div style="%s">%s</div>',
        sprintf(
            'background: var(--wp--preset--color--vivid-purple, #9b51e0); color: var(--wp--preset--color--white, #ffffff); padding: var(--wp--preset--spacing--20, 1.5rem); font-size: %s;',
            esc_attr( $options['size'] )
        ),
        esc_html( $options['message'] )
    );
}

または、長いインライン CSS を避けたい場合は、WP_Style_Enginecompile_css メソッドを使用できます。

function unadorned_announcement_bar_front_page() {
    // ...

    $css = WP_Style_Engine::compile_css(
        array(
            'background' => 'var(--wp--preset--color--vivid-purple, #9b51e0)',
            'color'      => 'var(--wp--preset--color--white, #ffffff)',
            'padding'    => 'var(--wp--preset--spacing--20, 1.5rem)',
            'font-size'  => $options['size'],
        ),
        ''
    );

    printf(
        '<div style="%s">%s</div>',
        esc_attr( $css ),
        esc_html( $options['message'] )
    );
}

結果は同じです

Table of Contents