As WordPress continues to evolve, the Gutenberg editor has become an integral part of the content creation experience. For developers, this shift presents an exciting opportunity to extend WordPress’s functionality through custom blocks. By leveraging React, we can create powerful, interactive blocks that enhance the editing experience and unlock new possibilities for content creators.

In this guide, we’ll walk through the process of creating custom Gutenberg blocks using React, from setting up your development environment to publishing your block for use in WordPress sites.

1. Understanding Gutenberg and React

Before we dive into development, let’s briefly recap why Gutenberg uses React and what this means for block development:

  • Gutenberg is built with React, a popular JavaScript library for building user interfaces.
  • Custom blocks are essentially React components with additional WordPress-specific functionality.
  • Understanding React concepts like components, state, and props is crucial for effective block development.

2. Setting Up Your Development Environment

To get started with custom block development, you’ll need to set up your environment:

a) Install Node.js and npm

Ensure you have Node.js and npm (Node Package Manager) installed on your system. You can download them from the official Node.js website.

b) Install the @wordpress/scripts package

This package provides a set of scripts for WordPress development. Install it globally:

npm install -g @wordpress/scripts

c) Create a new plugin directory

In your WordPress installation’s wp-content/plugins directory, create a new folder for your custom block plugin.

d) Initialize your project

Navigate to your plugin directory in the terminal and run:


npm init
npm install @wordpress/scripts --save-dev
  

3. Creating the Basic Block Structure

Let’s create a simple custom block to get started:

a) Create the main plugin file

In your plugin directory, create a file named my-custom-block.php:


<?php
/**
 * Plugin Name: My Custom Block
 * Description: A custom Gutenberg block created with React
 * Version: 1.0.0
 * Author: Your Name
 */

function my_custom_block_init() {
    register_block_type( __DIR__ );
}
add_action( 'init', 'my_custom_block_init' );
  

b) Create the block files

Create a src directory in your plugin folder with two files:

index.js:


import { registerBlockType } from '@wordpress/blocks';
import { useBlockProps } from '@wordpress/block-editor';

registerBlockType( 'my-plugin/my-custom-block', {
    title: 'My Custom Block',
    icon: 'smiley',
    category: 'common',
    edit: function() {
        const blockProps = useBlockProps();
        return (
            <div { ...blockProps }>Hello from the editor!</div>
        );
    },
    save: function() {
        const blockProps = useBlockProps.save();
        return (
            <div { ...blockProps }>Hello from the frontend!</div>
        );
    },
} );
  

style.css:


.wp-block-my-plugin-my-custom-block {
    background-color: #f0f0f0;
    padding: 20px;
    border: 1px solid #ddd;
}
  

c) Configure your block

Create a block.json file in your plugin’s root directory:


{
    "apiVersion": 2,
    "name": "my-plugin/my-custom-block",
    "title": "My Custom Block",
    "category": "common",
    "icon": "smiley",
    "description": "A custom block created with React",
    "textdomain": "my-plugin",
    "editorScript": "file:./build/index.js",
    "editorStyle": "file:./build/index.css",
    "style": "file:./build/style-index.css"
}
  

4. Building and Testing Your Block

Now that we have our basic structure, let’s build and test the block:

a) Add build scripts

In your package.json file, add these scripts:


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

b) Build your block

Run the build command to compile your block:

npm run build

c) Test your block

Activate your plugin in WordPress and try adding your custom block in the Gutenberg editor.

5. Enhancing Your Block with React Components

Let’s make our block more interactive by adding some React components:


import { registerBlockType } from '@wordpress/blocks';
import { useBlockProps, RichText } from '@wordpress/block-editor';
import { useState } from '@wordpress/element';

registerBlockType('my-plugin/my-custom-block', {
    title: 'My Custom Block',
    icon: 'smiley',
    category: 'common',
    attributes: {
        content: {
            type: 'string',
            source: 'html',
            selector: 'p',
        },
    },
    edit: function(props) {
        const { attributes, setAttributes } = props;
        const blockProps = useBlockProps();
        const [count, setCount] = useState(0);

        return (
            <div { ...blockProps }>
                <RichText
                    tagName="p"
                    value={ attributes.content }
                    onChange={ (content) => setAttributes({ content }) }
                    placeholder="Enter your text here..."
                />
                <button onClick={() => setCount(count + 1)}>
                    Clicked {count} times
                </button>
            </div>
        );
    },
    save: function(props) {
        const blockProps = useBlockProps.save();
        return (
            <div { ...blockProps }>
                <RichText.Content tagName="p" value={ props.attributes.content } />
            </div>
        );
    },
});
  

This enhanced block now includes editable text content and a clickable button that demonstrates React state management.

6. Adding Block Controls

Gutenberg provides various components for adding controls to your block. Let’s add some:


import { registerBlockType } from '@wordpress/blocks';
import { useBlockProps, RichText, InspectorControls } from '@wordpress/block-editor';
import { PanelBody, ColorPicker } from '@wordpress/components';

registerBlockType('my-plugin/my-custom-block', {
    // ... previous block configuration ...
    attributes: {
        content: {
            type: 'string',
            source: 'html',
            selector: 'p',
        },
        backgroundColor: {
            type: 'string',
            default: '#ffffff',
        },
    },
    edit: function(props) {
        const { attributes, setAttributes } = props;
        const blockProps = useBlockProps({
            style: { backgroundColor: attributes.backgroundColor },
        });

        return (
            <>
                <InspectorControls>
                    <PanelBody title="Block Settings">
                        <ColorPicker
                            color={ attributes.backgroundColor }
                            onChangeComplete={ (color) => setAttributes({ backgroundColor: color.hex }) }
                        />
                    </PanelBody>
                </InspectorControls>
                <div { ...blockProps }>
                    <RichText
                        tagName="p"
                        value={ attributes.content }
                        onChange={ (content) => setAttributes({ content }) }
                        placeholder="Enter your text here..."
                    />
                </div>
            </>
        );
    },
    save: function(props) {
        const blockProps = useBlockProps.save({
            style: { backgroundColor: props.attributes.backgroundColor },
        });
        return (
            <div { ...blockProps }>
                <RichText.Content tagName="p" value={ props.attributes.content } />
            </div>
        );
    },
});
  

This version adds a color picker in the block’s settings panel, allowing users to change the block’s background color.

7. Handling Block Styles

To make your block visually appealing and consistent with WordPress styles, consider these tips:

  • Use WordPress components and existing styles where possible to maintain consistency.
  • Create editor-specific styles to ensure your block looks good while editing.
  • Use CSS modules or CSS-in-JS solutions to scope your styles and avoid conflicts.

8. Testing and Debugging

Thorough testing is crucial for block development:

  • Use the WordPress Block Editor Validator to check your block for errors.
  • Test your block in different themes and with other plugins to ensure compatibility.
  • Use browser developer tools to debug React components and track state changes.

9. Publishing Your Block

Once your block is ready, you can publish it:

  • Package your block as a WordPress plugin.
  • Submit it to the WordPress plugin repository or distribute it through your own channels.
  • Provide clear documentation on how to use and customize your block.

Conclusion

Creating custom Gutenberg blocks with React opens up a world of possibilities for extending WordPress functionality. By following this guide, you’ve learned the basics of block development, from setting up your environment to creating interactive, customizable blocks.

Remember, the key to successful block development is understanding both React principles and WordPress-specific APIs. As you continue to develop blocks, explore the WordPress Block Editor Handbook and stay updated with the latest Gutenberg developments.

With practice and experimentation, you’ll be able to create sophisticated, user-friendly blocks that enhance the WordPress editing experience and bring new capabilities to content creators. Happy coding!