/ wordpress

How to prevent Gutenberg from flickering in Wordpress when editing text inputs for server side rendered blocks

Have you ever tried to create a server side rendered block that updates its content in Gutenberg every time you change attributes using the ServerSideRender component? This becomes very nasty if you change text attributes. Because every new character input will cause Gutenberg to query the server for a newly rendered version of the block. This behavior also teases the server.

This is nasty

ssr_before

This looks much better

So I had the Idea to create a wrapper for the ServerSideRender React component called DelayedServerSideRender. This wrapper prevents this annoying behavior by adding a delay to the renderer. If anybody starts to insert text data the wrapper component will wait a second after the last change before querying the server.
ssr_after

How does it work?

Note: The following examples are in ES5 but I'am sure you can translate them easily.

Instead of using the ServerSideRender I will now use the DelayedServerSideRender. As you can see, you can push the delay time as a prop:

var el = wp.element.createElement;
var registerBlockType = wp.blocks.registerBlockType;
var TextareaControl = wp.components.TextareaControl;
var Fragment = wp.element.Fragment;
var BlockControls = wp.editor.BlockControls;
var InspectorControls = wp.editor.InspectorControls;

registerBlockType( 'my/test', {
    title: 'Test',
    icon: 'megaphone',
    category: 'widgets',
    edit: function( props ) {
      var test = props.attributes.test;
      function onChangeTest( newValue ) {
        props.setAttributes( { test: newValue } );
      }
  		return (
        el(
            Fragment,
            null,
            el(
                InspectorControls,
                null,
                el(
                  TextareaControl,
                  {
                    placeholder: 'The test text',
                    label: 'hehe',
                    value: test,
                    onChange: onChangeTest,
                  }
                )
            ),
            el(DelayedServerSideRender, {
      				block: "my/test",
      				attributes:  props.attributes,
                    delay: 1000
      			})
        )
  		);
  	},

    save: function() {
        // Rendering in PHP
        return null;
    },
} );

Create and mount the DelayedServerSideRender in Wordpress

Create a new file called DelayedServerSideRender.js with the following contents:

DelayedServerSideRender.prototype = Object.create(React.Component.prototype);
function DelayedServerSideRender(props) {
  React.Component.constructor.call(this);
  var self = this;
  self.state = {
    attributes: props.attributes
  };
  self.componentWillReceiveProps = function(nextProps) {
    if(self.timeout){
      clearInterval(self.timeout);
    }
    self.timeout = setTimeout(function(){
      self.setState(function(prevState) {
        return { attributes: nextProps.attributes };
      });
    }, props.delay);
  };
  self.componentWillUnmount = function() {
     clearInterval(self.timeout);
  };
  self.render = function() {
    return el(ServerSideRender, {
      block: self.props.block,
      attributes:  self.state.attributes
    });
  }
}

Than mount the file in your Wordpress theme or plugin:

add_action( 'init', function(){
  wp_register_script(
      'DelayedServerSideRender',
      get_template_directory_uri().'/assets/js/DelayedServerSideRender.js',
      array( 'wp-blocks', 'wp-element' )
  );
} );

If you register a block, that depends on the DelayedServerSideRender you can specify this dependency in the wp_register_script function:

wp_register_script(
  'block_name',
  get_template_directory_uri().'/blocks/test/block.js',
  array( 'wp-blocks', 'wp-element', 'DelayedServerSideRender' )
);

Why I prefer server side rendered blocks

Server side rendered blocks are a good choice for large projects with many posts and pages. Consider the following situation: You have a Wordpress Blog with custom Blocks used in hundreds of posts. And now, how do you change the markup of a block type without editing each post again? The only solution are server side rendered blocks because their HTML is not stored inside the content.

GitHub example theme

If you need a boilerplate to start you can use this git repository where I have bundled everything into an example theme: https://github.com/steampixel/DelayedServerSideRender

How to prevent Gutenberg from flickering in Wordpress when editing text inputs for server side rendered blocks
Share this