This is the third post in a series on learning React, for use with Gutenberg, the new WordPress block-based editor that will be powering the WordPress post editor in WordPress 5.0. React is built on top of Facebook’s React library.
In this post, we’re going to take the code from the previous two tutorials and combine them. The first post just showed a very basic “Hello World” Gutenberg block. The last post backed up to a React “Hello World” example and then showed how to add components, such as those to show WordPress posts. Now in this post, we’re going to combine the two. We’ll put all of that example code together.
Using React With Gutenberg
As I explained in my previous post, Gutenberg has a thin abstraction layer over React. It’s worth looking at how this works in the source code, which is here. WordPress imports React.createElement and then exports it unmodified. That means React.createElement and wp.createElement are the same thing. Same thing for React.component. There is no extra complication there for now.
This thin abstraction exists to give WordPress flexibility in how we deal with changes to React’s API. We can’t predict the future of React, but this layer black-boxes React so that’s Gutenberg’s concern, not ours.
In the WordPress admin, on a Gutenberg screen, there are new objects attached to the “wp” global. For example, wp.element.createElement is available for creating HTML elements, and wp.blocks.registerBlockType is available for registering blocks. Therefore you do not need to load React on the page. In fact, you should not. You do not want a second copy of React.createElement when wp.element.createElement is there and is the same thing.
Using React Components In Your Blocks
In the first post in this series, I showed a very basic Hello World block, based on the official examples:
Let’s walk through this a bit. The function registerBlockType takes two arguments. The first argument is the namespace and name of the block. The namespace should be your plugin’s slug and be used for all of your blocks. After the slash is the name of your block. That way if I register calderawp/blockquote it doesn’t conflict with core/blockquote.
The second argument is an object that makes the block. This example has the most basic options. We give the block a name and assign it to categories. Below that, we have an edit callback and a save callback. The edit callback is the function uses to build the block’s interface.
The save callback may be used to save HTML content to post content. That is how this block works. When you add it to a post, the HTML you see in the save callback is saved to post content. Now you have HTML in your post content.
What About The Front-End?
Using React In Gutenberg
Let’s build on what we learned previously to expand our block and introduce attributes. Here is a slightly more complex version of our Hello World block, where the content comes from a Gutenberg attribute:
In this case, we added an extra key to our block arguments called “attributes.” The attributes of a block are the properties of the block that are saved. We added one attribute called “message” and gave it a default value. In the edit callback, I used the “props” passed to the edit callback to access the attributes.
I also changed the save callback so it returns null. Because I did that, Gutenberg will save the attribute values as an HTML comment in post content. That comment will be stripped out at render-time. You can use a PHP render callback, like a shortcode callback or you can save the attributes in HTML markup, or you can save them in post meta. There are a lot of options documented here.
Let’s stick to learning React.
So far we’ve used props.attributes in the edit callback to read the value of the attribute, but what if we wanted to change it? That’s where the function setAttributes(), which is in that object props comes in handy:
Now we have a simple text control when it changes its value — when the onChange callback is called. The new value will be passed to setAttributes().
The HTML that the last example creates is not good. The text input has no label. I could add a label element, and an element to put them in, or I could use Gutenberg’s text control which does that and more for me.
Show Different Stuff When Block Is Selected
Right now, the block always shows the control for editing the message. It never actually shows the message. That’s not how Gutenberg should work. Instead we want to show the control when editing the block and when not editing the block.
In the edit callback, props.isSelected will be true when the block is selected and false when it is not. So we can base a conditional on that:
This series continues next week. Fair warning, I get pretty advanced fast. If you’re looking for something that will walk through and build on each concept, WordPress.tv is filling up nicely with Gutenberg related content, including a ton of good developer facing talks.