Gutenberg is coming and we need to be prepared for it. In this tutorial, we will learn how to create a block that will display a post.

Last edited on May, 15th so the code can be used with the lastest Gutenberg release. Thanks to all my readers for providing feedback.

Preparing the Plugin

For our own Gutenberg Block for Display a Post, we will use the npm package Create-Guten-Block from Ahmad Awais. You will need to have npm and node installed on your machine. If you don’t have them, check this site and follow their install instructions.

Also, install the package create-guten-block by typing npm install create-guten-block --global so you can access it in any folder.

Since I will use that package, I don’t need to create a base of my plugin. Everything is done from there. I only have to place myself inside the plugins folder of my WordPress site (through the command line/terminal) and type create-guten-block guten-load-post. This will create a plugin guten-load-post. Once it’s installed just place yourself inside that folder with cd guten-load-post and then start it by npm start. You’re good to go for developing your own block.


The folder that we will use is src/block and the files inside are block.jseditor.scss and style.scss. We do have some code populated there so we have the essentials placed. Since I won’t use the front styles, I’ll have the content from style.css removed. Just leave it empty if you want o do something else later with it.

Inside the editor.scss I will place these:

This style rules will have a simple animation when loading the post.

The file block.js is the main file that we will use and the code we will write in this tutorial will go in there. Let’s just change a few parameters here such as title and keywords:

Activate the Plugin

Now go to Plugins and activate our plugin. For now, it should be called something like “guten-load-post — CGB Gutenberg Block Plugin”. You can change that in the file plugin.php.

Load a Gutenberg Post and check if our block is there. It should look something like this:

Understanding the Workflow

Before we get into creating our Gutenberg Block for Displaying a Post, we should understand how that will work. That way we can plan the block better.

So, the first thing we would need is a way to select the post to display. We will have that as a Block setting in the form of a drop-down of recent posts. Once the post is selected, we will get that post object and set the title, URL and excerpt from it as attributes.

To control how this is rendered inside the Gutenberg we would require states. With states, we will know which content or message to display. Instead of a regular edit function, we should use the React Component as the edit function so we have everything we need to manage states.

Gutenberg Block Attributes

Attributes are those that you can use to change how something looks. Similar to State in regular React. We will use that here to store our post information. Let’s set them after the keywords:

The attribute selectedPost will be set here as the ID of the post. You can then use that to filter the post or anything else related to that post. Other three attributes are self-explanatory: title, link to the article and content (excerpt).

Gutenberg Edit Component

Now, we will work on the edit component (function). We now need to import several parts for the edit part to work for our Gutenberg Block for Displaying a Post.

Let me try to explain what we did here. Besides importing registerBlockType from wp.blocks, we are also importing InspectorControls so we can have custom block settings (on the right sidebar in Editor).

Since we will also need a drop-down control, we are importing SelectControl from the previously imported InspectorControls.

The last import is Component for creating custom React Components. After we have everything set, we can create our custom mySelectPosts component and put it in place of the edit function. For now, we are just rendering a simple sentence there to test if we are correct.

Be sure to reload the Gutenberg Editor by refreshing the page and try adding our new block. It should show something like these:

Preparing our Component

Before we dive into more coding we need to prepare our component. This means that we need to setup the state and also the drop-down. We should be getting this when we click on our block (after using the next code):

We need a drop-down for selecting a recent post. This will be done inside the InspectorControls. For an easier understanding, just view it as a metabox (container of fields) for the Gutenberg Editor. With InspectorControls we can add as many inputs (controls) as we want.

In the code above we have created a method to set the initial state. This method is called in the constructor method. We are setting the initial state and also by using super(), we are setting everything up and enabling our own properties to be available in it.

Inside the render method, we are defining options that will hold all the posts that we can select. For now, we have only one option. The last thing we do is refactor the return. Now, we are returning an array so that we can have more than 1 return value.

We are checking if our block is selected with !! this.props.isSelected. If it is, then we are enabling the InspectorControls. We are putting our SelectControl as an element of the wp.components. You can put as many controls as you want there. The value of our control will be the select ID of the post and the options that represent the posts we can select are placed inside the options attribute. For now, we won’t have any posts to select.

Creating the Output

Let’s now change the text in the render method. We want the text to show the status of our block. If we have some posts, we will tell the user that he should select one. If there are no posts, then we will tell our user to create some.

At the beginning of the render method, we are defining another let variable output. This will hold the status of our block or the selected post. The first status will be Loading Posts. If there are no posts, we will show that the user should create some. If there are posts, we will then add them as new options inside our variable options.

If you save this and try to add our block inside the Gutenberg Editor, it will show that there are no posts found. That is because we have yet to define our method that will load the posts.

Loading Posts

For loading our posts, we need a method that will do just that. And we will also call this method when the block is created (inside the constructor method).

In the constructor method, we are binding getOptions method to this so that we can have access to attributes and method through this inside the getOptions. After that, we are also calling that method so that we can get those recent posts right after the block has been created.

Inside the method getOptions, we are fetching the latest posts through wp.api. We are checking if we have retrieved any posts. If there are any posts and if we already have a selected post, then we are finding that post. The last part is updating the state of our component with posts and the found post.

Do not that we are using modern JavaScript here so you don’t have to set the key in the objects if it’s the same name as the variable we are putting in. That is why we are using { post, posts } instead of  { post: post, posts: posts }.

Now, if you reload your Gutenberg editor (so the JavaScript reloads) your block will say that there are some posts loaded. You can go in the settings of the block and see a list of found posts.

Saving the Selected Post

To save the selected post, we need to have a method that will do that once our SelectControl changes its value. We will create a new method onChangeSelectPost and we will put that method as an onChange event in the SelectControl.

We are binding our new method to this inside of the constructor method so we can have other methods and attributes available through this.

First, we are finding a select post by the value provided. The provided value will be an ID. After that, we are setting the state and attributes. I did not check if the post is found here, so you can do that for practice.

Inside the render method, the only change we did is to add our new method to an onChange event.

Displaying the Selected Post in the Editor

We now have everything in place and the last part of our Edit Component is to show the selected post. We will do that all inside the render method.

First, we are setting a class loading. After that, we are checking if our post inside the state has a property title. If it has, it means that we have loaded posts and found the selected one. If that property is not found, then it means that the post is empty.

If it’s empty, then we are adding a class no-post. If there is a post, then we are using  JSX to create the output. We are creating a simple output with a linked title and some content. We could (or even should) use the attributes here, so be sure to try that out as a practice. We are also using dangerouslySetInnerHTML to render the content with encoding. You can read more about that here:

The last thing is to wrap the output in a div element with classes. This will also add our class that we have defined in our editor.scss. We are now done with the Edit part of our Gutenberg Block for Displaying a Post.

Gutenberg Saved Output

To define how our block will look in the front of our site, we need to edit the save method of our block. We will use attributes here in creating the whole output. It is not so different than the output of the edit component.

Save everything and try to reload the Gutenberg Editor. If you have already tested the outcome of this block, you will get an error on your block. You will have to click on the Overwrite button.


Creating Gutenberg Blocks can be a lot of fun. You can write this blocks even with ES5 JavaScript. I would recommend you to try and switch to modern JavaScript.

In the above code, there are a few parts that could be refactored and I would invite you to try and do that.

Have you tried building your own Gutenberg Blocks? Were there any struggles you had when building one? Show us what you did in the comments below:)

Join the Webinar!

Posted by Igor Benic

Web Developer who mainly uses WordPress for projects. Working on various project through Codeable & Toptal. Author of several ebooks at


  1. Can we download the plugin for test? Does it work with more than 100 posts in system? I am looking for solution for more than 100 entries, I can’t find one. I have already asked at other blogs but no answer (


    1. I am using the backbone client through wp.api.collections.Posts() and for more posts you would have to pass that option when fetching the results. Check out the REST API Handbook:


  2. Thank you, but I have tried all options but can not get more results as 100 in one pass. 🙁


    1. It seems that 100 is the limit now. But you can try something like in this answer:


  3. Unfortunately this does not work.


    1. Sorry about that. You may need to paginate through the results then.


      1. How would paginate work in a code like the “Select a Post” dropdown in your plugin? I am not coding so good, maybe I do not see something, please help.


  4. Thanks for this. Its the nearest of what I hope as answer to the use of select fields in Gutenberg Block admin. My purpose rejoins Hendrik’s question because a selector of over 100, even over 20 is of no practical use. Do you know about adding autocomplet capacity to SelectControl. In the way of select2, reducing the option list with each char typed in an imput field.


    1. I had hosted a webinar on using autocomplete For now, it does similar as the dropdown in here. But maybe the trigger in the autocomplete can be used to search for related posts.


  5. Good stuff Igor!

    I’m trying to figure out how to pull a featured image, along with the post’s title, link and except — but I’m running into a few snags. Any advice you could point out for me would be super appreciated!


    1. Hi Rich, really glad you find it useful! To pull the featured image, you would need to create an additional fetch on it. Each post JSON has a featured_media attribute. This holds an ID. Then you can fetch the media info through /wp-json/wp/v2/media/{MEDIA_ID}. The retrieved object would then have an attribute source_url that will hold the featured image URL.

      Maybe the easiest approach would be to create a custom REST endpoint to retrieve only what you need for the Gutenberg block:D


      1. Ah, interesting! Thanks for the pointer — I’ll see what I can do. 👍


  6. Hi,

    Thanks so much for the tutorial! There are very few resources available for building Gutenberg blocks, and none that I’ve found have gone as in depth as yours. I really appreciate you taking the time to write yours.

    I did run into an error around blockedit2.js:

    ‘Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined.’

    I was able to fix it by changing the declaration of SelectControl to the following:

    const { SelectControl } = wp.components;

    It’s likely the error was my own doing, but thought I’d throw it out there just in case others are having the same issue. Other than that, everything ran fantastically. Thanks again! 🙂


    1. Thanks, Chris, that changed declaration helped me!


  7. Awesome and very useful tutorial, i struggled to find a good example of querying posts in a Gutenberg block, so many thanks !

    PS : i had the same issue than Chris, resolved the same way, probably from a Gutenberg recent release.


  8. Beginner’s question. In G 2.8.0 focus has been “replaced” with isSelected.

    How to adjust your code to this update?


    1. Alright, I found that it is as easy as writing !! this.props.isSelected

      But my problem came from the other flank. I had to change const { SelectControl } = InspectorControls; to const { SelectControl } = wp.components;


  9. Also, I couldn’t simply append ‘ loading’ this.props.className
    because the nature of the property Uncaught TypeError: Cannot assign to read only property 'className' of object


    1. Hi Przemek, I’ll look into that and update the code accordingly. It will probably be updated in a few days when I get some free time.


Leave a reply

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

This site uses Akismet to reduce spam. Learn how your comment data is processed.