An Improved Server Side Render Component for Dynamic WordPress Blocks

If you’ve developed dynamic blocks for the WordPress Gutenberg editor before then you may have encountered a common rendering issue whenever changes are made to block attributes.

More specifically, when using the core <ServerSideRender/> component inside a dynamic block it momentarily replaces the block HTML content with a spinner while waiting for new content to be sent from the server.

Before/During Render Cycle

This is especially noticeable when making multiple changes in quick succession. e.g. when tweaking block settings via the block inspector panel.

Tweak Block Attributes

As you can see, changes between render states for dynamic blocks are far from ideal. In this post, we’ll dig deeper into why this happens and how you can use a new editor component, we’ve developed, in your own projects to improve the rendering experience.

Show me the Solution Already!

Before we go any further, if you just want to find out how to fix the rendering issue for dynamic blocks then here’s a quick link to the solution contained in a GitHub repository.

Simply follow the instructions in the repository readme.md file to begin using it in your own blocks right away!

What Are Dynamic Blocks?

You’ll typically come across dynamic blocks whenever you need to display non-static HTML content, such as listing the latest blog posts on your site. Obviously, the list of posts will change over time as you write new content so you don’t want to ‘hard code’ them inside a block.

This is where dynamic blocks come into their own. They allow you to develop blocks that render content that could change over time by using PHP to render block content. Instead of serving block content directly from the database (as is the case for static blocks), it’s generated when needed on the server and rendered in the editor, or on the frontend of your site.

This is very similar to how shortcodes work. A specific shortcode string is added to the editor and then when the page is loaded on the front end the shortcode is converted into HTML content via executing a PHP function. The major difference of course is that with shortcodes you have no preview at all in the editor but with blocks, you see a live preview of the content in real-time.

Incidentally, using dynamic blocks is an ideal approach to convert a shortcode to an editor block as you can use most of the existing PHP code to render block content. In fact, this is probably one of the most common uses of dynamic blocks and is a great way to create a block version of your shortcodes. And with a little careful coding, you can pretty much use the same codebase for blocks AND shortcodes!

How Dynamic Blocks are Currently Rendered

To render a dynamic block you first need to add the core <ServerSideRender/> component. This is easy as it’s included with WordPress by default and its primary purpose is to render content generated from a PHP function (i.e. similar to how shortcodes work).

Typical usage is:

const { serverSideRender: ServerSideRender } = wp;
 
const MyServerSideRender = () => (
  <ServerSideRender
    block="core/archives"
    attributes={ {
      showPostCounts: true,
      displayAsDropdown: false,
    } }
  />
);

More details on the component and props can be found here.

Once implemented here’s how the block looks when transitioning between render states.

Tweak Block Attributes

As we saw earlier, the problem is clearly evident. Every time a block attribute changes it causes the underlying PHP function to be run again to generate new block content. Unfortunately, every time this happens, the <ServerSideRender/> component temporarily replaces the entire block content with the <Spinner/> component while waiting for new content. This behavior is fixed inside the component and can’t be changed.

Here’s the component code that handles the placeholder content.

LoadingResponsePlaceholder: ( { className } ) => {
  return (
    <Placeholder className={ className }>
      <Spinner />
    </Placeholder>
  );
},

The full source code for the component can be seen here.

Inspiration for the Solution

Over the last couple of years, we’ve developed numerous blocks here at WPGO Plugins, a lot of which are dynamic. The rendering experience when using the core <ServerSideRender/> component has really never been satisfactory but it’s something that we’ve had to live with, until now.

At one point we even considered splitting the codebase for dynamic blocks and having the frontend render via PHP and the editor in pure (React) JavaScript so the editing experience would be more fluid.

However, this method would soon cause development and maintenance to become way too expensive. It’s also very prone to errors, even for simple plugins, which would lead to an even poorer user experience. Also, for larger plugins containing multiple (non-trivial) blocks then forget it – the development cost would far out way any benefits!

The inspiration came when I was recording a screencast for a new block inspector control for border styles for our Flexible FAQs plugin. When editing the final video the constant flash of the grey background and <Spinner/> component when transitioning between old and new block content was so jarring I actually started to edit these out of the video.

Initially, I thought there’s no way these could be left in the screencast as it could put off potential customers but, of course, this was never really a viable option. For a start, there were so many spinner flashes to edit out (even for a reasonably short video) that it would be very time consuming to remove every single one. And secondly, I wasn’t comfortable just covering up the problem as that wouldn’t be addressing the core issue at all.

There had to be a better way. We came to realize that only a change at the component level would work, which meant that the core <ServerSideRender/> component in its current form couldn’t be used.

Introducing the new Server Side Rendering Component

In the end, the only solution that made sense was to create a new server-side render component based on the existing core <ServerSideRender/> component, and altering the way it handles block content between render states.

The final result was better than expected and improves the rendering to such an extent that it looks almost as smooth as pure JavaScript based blocks!

Tweak Block Attributes - New

The new component is called <ServerSideRenderX/> so as not to change the original component name too much, but also to indicate that this version improves the user experience (i.e. X being used to represent ‘user experience’).

The new component works by using an additional piece of component state to track the previous block content. So now when attempting to fetch new content (when a block attribute has been updated) the previous content is used as the placeholder content in between render states, instead of just displaying the <Spinner/> component.

The key to this approach is that the waiting/loading content (between render states) does not interfere with the current block content. Then when the new content is ready to be loaded the transition is practically seamless. This has quite a dramatic effect on rendering compared to the core <ServerSideRender/> component.

Because the new component is based on the core component, usage is almost identical. In fact, the only changes needed are to make sure the new component is imported into your block correctly and to change the name of the component:

import { ServerSideRenderX } from '../__components/server-side-render-x';

...

<ServerSideRenderX
  block="flexible-faqs/accordion-expand-faqs"
  attributes={attributes}
/>

Incidentally, the new component placeholder (based on the previous block content, remember?) also includes a spinner. This has to be included of course to provide visual feedback that a block update is pending.

This actually turned out to be trickier than expected as it had to be added as raw HTML so we couldn’t use the <Spinner/> component (because it’s a React component, not HTML). But with a little bit of tweaking we got the spinner to work properly, and the overall effect is definitely worth it.

An Added Bonus

By default, the spinner used in <ServerSideRenderX/> is located at the top right of the block.

New Spinner Location

This is fine in most cases but occasionally you might need to tweak the location depending on the currently active theme. So, to make the component more flexible an additional prop was added to change the spinner location to whatever you want:

<ServerSideRenderX
  block="flexible-faqs/accordion-expand-faqs"
  attributes={attributes}
  spinnerLocation={{right: 0, top: 10, unit: 'px'}}
/>

These are the default settings for the spinnerLocation prop so there’s no need to use it at all if the default values are OK, you can just leave it out entirely.

Time for Action!

It took a while to figure out the best approach for optimizing block content between render states but we’re really pleased with the final result. The <ServerSideRenderX/> component works very well and has passed testing (for several months) with flying colors.

It’s now used in a production plugin, and we’ll soon be adding it to all our other dynamic blocks too, and I encourage you to do the same. But don’t take my word for it, try it out for yourself. Grab the new improved Server Side Render component here.

Enjoy!