How to create a WordPress React settings page

·

·

In this tutorial I’m going to show you how to create a settings page using WordPress React components. Here you’ll find the GitHub repository with the finished code.

Creating the plugin boilerplate

First of all let’s create the development environment installing the @wordpress/env package which will provide us with a local WordPress installation ready for development:

npm i @wordpress/env --save-dev

As we are going to create a plugin, let ‘s create a .wp-env.json file in the root of the project with the following content:

{
  "plugins": [
    "."
  ]
}

The above file instructs wp-env to automatically install and activate our plugin on the WordPress site.

Next let’s install @wordpress/scripts which will help us building all the assets:

npm i @wordpress/scripts --save-dev

Once installed add the following scripts to your package.json:

  "scripts": {
    "build": "wp-scripts build",
    "start": "wp-scripts start",
    "wp-env": "wp-env"
  }

Create an index.js file inside an src folder in the root of the project, this will be the entry point of the React application:

console.log('Hi there!');

Run build command to compile the assets, a new build folder will be created at the root of the project with the compiled assets:

npm run build

Finally, let’s create an index.php for the plugin file and the settings page:

<?php
/**
 * Plugin Name: React Settings Page
 */

if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

add_action('admin_menu', function () {
    add_menu_page(
        'React Settings Page',
        'React Settings Page',
        'manage_options',
        'react-settings-page',
        function() {
            echo '<div id="react-settings-page">React App goes here...</div>';
        }
    );
});

add_action( 'admin_enqueue_scripts', function($page) {
    if($page !== 'toplevel_page_react-settings-page') {
        return;
    }

    $asset_file = require __DIR__ . '/build/index.asset.php';

    wp_register_script(
        'react-settings-page',
        plugins_url( '/build/index.js', __FILE__ ),
        $asset_file['dependencies'],
        $asset_file['version'],
        true
    );

    wp_enqueue_script( 'react-settings-page' );
    wp_enqueue_style( 'wp-components' );
});

Now that we have included all the boilerplate it’s time to run the site which will be available at http://localhost:8888 using admin and password as admin credentials:

npm run wp-env start

If all previous steps went well you should now be able to see the plugin active, the settings page created and the React application file loaded correctly:

WordPress React settings page boilerplate

Adding WordPress React components

First of all add the following code to index.js:

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

domReady(() => {
    createRoot(
        document.getElementById('react-settings-page')
    ).render(
        <App />
    );
});

Then create a new file App.js with the following content:

import {__experimentalHeading as Heading, Card, CardBody, CheckboxControl, Button} from "@wordpress/components";
import {useState} from '@wordpress/element';

export const App = () => {
    const [checked, setChecked] = useState(false);

    return <>
        <Heading level={3} adjustLineHeightForInnerControls="large">React Settings Page</Heading>
        <Card>
            <CardBody>
                <CheckboxControl
                    label="Check me"
                    checked={checked}
                    onChange={() => setChecked(!checked)}
                />
                <Button variant="primary" onClick={() => console.log('click')}>
                    Save
                </Button>
            </CardBody>
        </Card>
    </>
}

The above code uses UI components from WordPress @wordpress/components package.

Reload the setting page and check the result:

WordPress React settings page with WordPress components UI

Persisting the setting

Finally we have to save the checkbox value to WordPress database, to do so we are going to register a setting with the following code, notice how in order to have the setting available in the REST API we are also registering it for the rest_api_init action hook:

function react_settings_page_register_settings() {
    register_setting(
        'react-settings-page',
        'react_settings_page_check_me',
        array(
            'type'         => 'boolean',
            'default'      => false,
            'show_in_rest' => true,
            'sanitize_callback' => fn($value) => (bool) $value,
        )
    );
}

add_action( 'admin_init', 'react_settings_page_register_settings' );
add_action( 'rest_api_init', 'react_settings_page_register_settings' );

Now that we have our setting registered it’s time to finish the React application by retrieving and saving it, here is the final code:

import {__experimentalHeading as Heading, Card, CardBody, CheckboxControl, Button} from "@wordpress/components";
import {useState, useEffect} from '@wordpress/element';
import apiFetch from '@wordpress/api-fetch';

export const App = () => {
    const [checked, setChecked] = useState(false);

    useEffect(() => {
        apiFetch({path: '/wp/v2/settings?_fields=react_settings_page_check_me'})
            .then((setting) => {
                setChecked(Boolean(setting.react_settings_page_check_me))
            })
    }, []);

    const saveSettings = () => {
        apiFetch({
            path: '/wp/v2/settings',
            method: 'POST',
            data: {
                react_settings_page_check_me: checked,
            }
        });
    }

    return <>
        <Heading level={3} adjustLineHeightForInnerControls="large">React Settings Page</Heading>
        <Card>
            <CardBody>
                <CheckboxControl
                    label="Check me"
                    checked={checked}
                    onChange={() => setChecked(!checked)}
                />
                <Button variant="primary" onClick={saveSettings}>
                    Save
                </Button>
            </CardBody>
        </Card>
    </>
}

That’s all, we have completed the steps for creating a very basic but functional WordPress React settings page.