Is Learning React Necessary for Block Development?

Edmund Chan

Watch the Live Talk from WordCamp Asia 2023

WordPress development used to be mostly about writing PHP and sometimes adding in sprinkles of JavaScript. But since 5.0, you can now rarely talk about WordPress development without mentioning JavaScript or more specifically React, the JavaScript library which the Block Editor is written in. So is learning React necessary for Block development?

And the answer is… It depends.

There are two approaches to Block development:

Gutenberg Block Development Using PHP

The first is lean towards PHP. This usually involves using third party solutions like Advanced Custom Fields or Meta Box Blocks that serve as a framework for you to create custom blocks in a way which you’re already comfortable with. Despite having their own system, there are still some similarities to how native WordPress handles things like block registration. For example, Advanced Custom Fields recommends and supports the use of block.json for configuring your block.

Here’s a simplified example of creating a testimonial block using the ACF framework (code taken and simplified from https://www.advancedcustomfields.com/resources/blocks/)

{
    "name": "acf/testimonial",
    "title": "Testimonial",
    "description": "A custom testimonial block.",
    "style": [ "file:./testimonial.css" ],
    "category": "formatting",
    "icon": "admin-comments",
    "keywords": ["testimonial", "quote"],
    "acf": {
        "mode": "preview",
        "renderTemplate": "testimonial.php"
    },
    "align": "full"
}

/blocks/testimonials/block.json

<?php 

/**
 * Registering your block using the native register_block_type function.
 */
add_action( 'init', 'register_acf_blocks' );
function register_acf_blocks() {
    register_block_type( __DIR__ . '/blocks/testimonial' );
}
<?php
/**
 * testimonial.php - block template
 */

// Load values and assign defaults.
$text   = get_field( 'testimonial' ) ?: 'Your testimonial here...';
$author = get_field( 'author' ) ?: 'Author name';

?>

<div>
	<blockquote class="testimonial-blockquote">
		<span class="testimonial-text"><?php echo esc_html( $text );?></span>
		<span class="testimonial-author"><?php echo esc_html( $author );?></span>
	</blockquote>
</div>

The most obvious benefit with this approach is how quick and easy it is to get up and running; you don’t have to worry about things like tooling or package management in order to start creating custom blocks.

It’s also worth mentioning that plugins like Advanced Custom Fields are very popular in the WordPress ecosystem. For some, those plugins are part of their ‘tech stack’ when building WordPress sites. Hence this “low barrier to entry” solution is especially popular among seasoned WordPress and PHP developers because you’re leveraging an already familiar API to do something new.

With this approach, you’ll be predominantly working with PHP; there’s very little need, if any at all, for JavaScript, let alone React.

So if you choose this route then no, it’s not necessary to learn React for Block development.

But the idea of adding another third party dependency or framework, especially for doing something that is fundamental to WordPress is a deal-breaker for many. Lack of future-proofing and incompatibilities are some valid reasons to stay away from them and stick closely to doing things the “WordPress Way”.

This brings us to the second approach.

Gutenberg Block Development Using JavaScript

Or rather mostly JavaScript. Like many other things in WordPress you can’t avoid writing PHP. In most cases though, we’re talking about minimal involvement i.e., for enqueuing scripts or registering blocks on the server-side. Apart from that, it’s JavaScript all the way down.

It’s worth mentioning for dynamic blocks, depending on its complexity there could be quite a bit of PHP required.

But because it’s JavaScript and React, two terms that aren’t synonymous with WordPress development until a few years ago, the barrier to entry is high; getting your local environment setup can sometimes be a mini-project by itself; tooling and configurations can be very daunting and it’s possible to spend hours on them before you get to write the first line of code for your block. Also, not everyone has the luxury of time to get up to speed with React and its ecosystem.

So why is this still a viable and, in most cases, the recommended approach?

Security, performance and future-proofing, just to name a few.

Since we are using the API provided by WordPress Core, we can be sure that they are widely tested and optimized for a more superior editing experience. Having one less third-party solution also means you’re less likely to encounter compatibility issues; the “WordPress Way” is also continually evolving and improving so sticking to it helps ensure your codebase remains up-to-date.

So does this mean it’s necessary to learn React for this approach? Again, it depends.

If you’re looking to create basic blocks with minimal settings then you don’t need to learn React. But having a cursory understanding of concepts like state, components and the JSX syntax does is very useful. And the Block Editor handbook is a good resource to help with that.

(simplified code taken from Create a Block Tutorial)

{
    "$schema": "https://schemas.wp.org/trunk/block.json",
    "apiVersion": 2,
    "name": "create-block/gutenpride",
    "version": "0.1.0",
    "title": "Gutenpride",
    "category": "widgets",
    "icon": "smiley",
    "description": "Example static block scaffolded with Create Block tool.",
    "attributes": {
        "message": {
            "type": "string",
            "source": "text",
            "selector": "div",
            "default": ""
        }
    },
    "textdomain": "gutenpride"
}

block.json

/**
 * Edit.js
 */

import { TextControl } from '@wordpress/components';
import { useBlockProps } from '@wordpress/block-editor';

export default function Edit( { attributes, setAttributes } ) {
    const blockProps = useBlockProps();
    return (
        <TextControl
            { ...blockProps }
            value={ attributes.message }
            onChange={ ( val ) => setAttributes( { message: val } ) }
        />
    );
}
/**
 * Save.js
 */

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

export default function save( { attributes } ) {
    const blockProps = useBlockProps.save();
    return <div { ...blockProps }>{ attributes.message }</div>;
}
Inserting our “Simple Block” into the editor
Inserting our “Simple Block” into the editor

For more advanced blocks that involve the WordPress’ data module or working with external data sources then yes, you should learn React. As the complexity of your block increases, chances are you will have to dig deeper into concepts like state management, lifecycle and hooks to help with debugging, avoiding common pitfalls (like the infinite loop in useEffect) and ensuring the end product works as intended.

On top of that, getting familiar with Redux, the state management library which the WordPress’ data module is inspired by, is also beneficial and important. And that because you’ll likely find yourself reaching out to the WordPress data store for things like getting the parent’s block client ID or all nested blocks inside a parent block.

/**
 * Using the WordPress data module to retrieve information of parent and nested blocks
 */

export default function Edit( props ) {
	// code removed for brevity

	// Selects nested Accordion-item blocks and index of each Accordion-item block.
	const { blockIDs, itemIndex } = useSelect( ( select ) => {
		// Gets ID of Accordion Parent block
		const parentOfSelectedBlock = select(
			'core/block-editor'
		).getBlockRootClientId( clientId );

		// Gets all nested Accordion item blocks.
		const blocksList = select( 'core/block-editor' ).getBlocks(
			parentOfSelectedBlock
		);

		return {
			blockIDs: blocksList.map( ( b ) => b.clientId ),
			itemIndex: select( 'core/block-editor' ).getBlockIndex(
				clientId,
				parentOfSelectedBlock
			),
		};
	} );

	// code removed for brevity
}

Knowing React is also incredibly helpful in understanding the Gutenberg source code to see how things are being done the “WordPress Way”. For instance, the core Button block has a nice little feature for improving accessibility. When you click on the “Link” block control, a popover appears and the focus automatically shifts to the input field.

Clicking on the same control again will cause the Button to be unlinked. At the same time, the focus automatically shifts back to the Button input. This nicety is achieved using refs in React.

Improving accessibility by auto enabling focus on the button after the popover closes.
/**
 * Simplified RichText Component using the forwardRef React API to receive the ref from its parent and forward it to a child component (<TagName />)
 */
 
function RichTextWrapper(props, forwardedRef) {
    return (
        <TagName 
            ref={ useMergeRefs( [
                forwardedRef,
                ...otherRefs,
            ] ) } // is this the correct syntax for spreading in array?
            {...otherProps}
        />
    )
}
const ForwardedRichTextContainer = forwardRef( RichTextWrapper );

export default ForwardedRichTextContainer;

The above is just one of the many examples of how knowing React allows you to not only handle complex blocks but also provide a better editing experience when users use your block.

The Two Approaches to Block Development

Next steps

So you have chosen your approach. What’s next? Here are some resources for both approaches to help you start writing your first block:

The Block Editor has been in development for about 5 years now and is not going to go away. So let’s help each other embrace this paradigm of working and developing with WordPress by teaching and sharing.