Replace a shortcode with a block using as little and simple code as possible

Earlier this week, Topher asked an interesting question on Twitter regarding the current state of block development:

Click here to display content from Twitter.
Learn more in Twitter’s privacy policy.

This made me think about I would answer this question. When I first started with block development, I primarily wrote “server side rendered blocks”. These blocks will not generate the content directly in the editor, but use some PHP code and a callback function to render the content, just as a shortcode would do.

The other difficulty with block development is the need to learn many new things: React, JSX, modern JavaScript compilation with webpack and much more. This all combined does not make it “as easy” as it was with shortcodes. But still I wanted to show, how little code you need to create a block that could possibly replace a shortcode without the need to learn all these new things.

Writing a server side rendered block – the PHP part

The easy part is registering the block and the render callback in PHP. While you would use the function add_shortcode() for a shortcode callback, you use a parameter when registering the block in PHP:

function rpssrb_init() {
	register_block_type(
		'rpssrb/random-posts',
		[
			'render_callback' => 'rpssrb_render_callback',
		]
	);
}
add_action( 'init', 'rpssrb_init' );

For this blog post, we will write a block that will render some random posts. The content of the callback would look just like with a shortcode. You can also use the same helper functions you would use for a shortcode. The callback might look like this:

function rpssrb_render_callback( $atts ) {
	$atts = shortcode_atts(
		[
			'post_type'      => 'post',
			'orderby'        => 'rand',
			'posts_per_page' => 5,
		],
		$atts
	);

	$query = new WP_Query( $atts );

	$output = '';
	if ( $query->have_posts() ) {
		$output .= '<ul>';
		while ( $query->have_posts() ) {
			$query->the_post();
			$output .= sprintf(
				'<li><a href=%s>%s</a></li>',
				get_permalink(),
				get_the_title()
			);
		}
		$output .= '</ul>';
	}

	return $output;
}

We set some default attributes and then run a WP_Query to get 5 random posts. We render them in a simple unordered list with only the title linked to the blog post.

Implementing the block in JavaScript – using ES5 code only

As mentioned before, one of the hardest parts of writing a block is need to learn React, JSX, etc. and compile this code. If you are not familiar with these technologies, it can be really hard to get started. This is why I want to show you how you can use some ES5 (“old JavaScript”) to write a block. All you really need is this:

wp.blocks.registerBlockType(
	'rpssrb/random-posts',
	{
		title: 'Random Posts',
		edit: function () {
			return wp.element.createElement(
				wp.serverSideRender,
				{
					block: 'rpssrb/random-posts'
				}
			);
		}
	}
);

We use the wp.blocks.registerBlockType function in ES5 style and only provide a title and the edit function. In this function, we create a React element with the wp.serverSideRender component that will render our block.

The edit function is used to show the content of the block (in our case the result of the callback function written in PHP). You don’t even need this, but then you would not see anything in the block editor (the block also does not take up any space as it’s empty), but it would render in the frontend.

Loading the JavaScript file

This JavaScript code has to be loaded when the block editor is used. If you already have some files being loaded for the block editor, just place it in this file. If not, you would enqueue it in the same way as usual, but with a different hook:

function rpssrb_register_scripts() {
	wp_enqueue_script(
		'random-posts-server-side-render-block',
		plugin_dir_url( __FILE__ ) . 'index.js',
		[ 'wp-blocks', 'wp-server-side-render' ],
		filemtime( plugin_dir_path( __FILE__ ) . 'index.js' ),
		true
	);
}
add_action( 'enqueue_block_editor_assets', 'rpssrb_register_scripts' );

In the dependencies, we add wp-blocks and wp-server-side-render, but they are usually loaded anyway when the block editor is used.

Bonus: use a shortcode as well

As we have written a callback function that we already know from shortcodes, we can simply add another line to make it usable as a shortcode as well (e.g. using the shortcode block):

add_shortcode( 'rpssrb_random_posts', 'rpssrb_render_callback' );

Caveat: using attributes is complicated!

The block we have built here cannot use any attributes. Adding them to the block would be easy, but implementing the controls to make them usable is not that easy. And while it’s doable using only ES5, I would not suggest doing this.

Consequence: Learn JavaScript, deeply.

As Matt has given us all as homework at WCUS 2015 I would highly suggest to start learning some modern JavaScript. The hardest part is getting started is the compilation using webpack. If you have no idea where to start, I would agree with the answer from Birgit to the tweet: use the create-block package.

The create-block package will not only help you to create a running block inside a WordPress plugin. It will also install all the JavaScript packages needed to compile the modern JavaScript. For this it’s using the @wordpress/scripts package and the main script you would use is the start script. Give it a try, read some documentation on how to add attributes and make your block even easier to use.

Conclusion: creating a block can be easy, but it might not be enough

While you can write a block as a simple replacement for a shortcode using only one PHP and one JavaScript file using ES5 syntax, I would not recommend it. Once you made yourself familiar with some basics, you can create blocks that improve usability dramatically. I know it sounds a bit intimidating, and you will run into all kinds of problems, but it’s worth it.

If you want to see the complete code of this blog post, you can find it on GitHub as a plugin.

Posted by

Bernhard is a full time web developer who likes to write WordPress plugins in his free time and is an active member of the WP Meetups in Berlin and Potsdam.

Leave a Reply

Your email address will not be published. Required fields are marked *