Day 17: Creating Server-Side Rendered Blocks in Gutenberg

Introduction

Welcome to Day 17 of the Gutenberg series! Today, we’ll cover server-side rendered blocks, which allow you to dynamically fetch and display content from the server, both in the editor and on the front end. Server-side blocks are particularly useful when you need to show real-time data, pull in posts, or display custom data from an external source.

In this guide, you will learn how to:

  • Create a basic server-side rendered block.
  • Fetch and display dynamic content from WordPress.
  • Customize the rendering logic using PHP.

What are Server-Side Rendered Blocks?

Server-side rendered blocks allow you to generate content on the server side rather than the client side (in the browser). This means the block’s content is fetched or processed by the server every time the block is rendered in the editor or on the front end. This approach is ideal for blocks that display real-time data or content that may change frequently, such as:

  • Recent Posts: Display the latest posts dynamically.
  • Custom Post Data: Pull in specific data from custom post types or metadata.
  • External APIs: Fetch and display data from an external source, such as weather updates, stock prices, or RSS feeds.

Step 1: Creating a Basic Server-Side Rendered Block

Let’s start by creating a block that fetches and displays the latest posts from your WordPress site.

  1. Register the Block in JavaScript

First, register the block in your JavaScript file (blocks/server-rendered-block.js). This block will use the ServerSideRender component to fetch content dynamically from the server.

import { registerBlockType } from '@wordpress/blocks';
import ServerSideRender from '@wordpress/server-side-render';

registerBlockType('my-theme/latest-posts-block', {
    title: 'Latest Posts',
    icon: 'list-view',
    category: 'my-custom-category',
    edit: () => {
        return (
            <ServerSideRender
                block="my-theme/latest-posts-block"
            />
        );
    },
    save: () => {
        return null; // Server-side block, no content saved
    },
});

Explanation:

  • ServerSideRender: This component automatically fetches the rendered block content from the server using the render_callback function in PHP.
  • save: null: Since this block is dynamically rendered on the server side, there’s no need to save any static content.

Step 2: Adding the PHP Render Callback

Next, we’ll define the logic for fetching the latest posts on the server side using PHP. This is where we’ll write the render_callback function.

Add the following code to your theme’s functions.php file:

function my_theme_render_latest_posts_block( $attributes ) {
    // Fetch the latest 5 posts
    $recent_posts = wp_get_recent_posts( array(
        'numberposts' => 5,
        'post_status' => 'publish',
    ) );

    if ( empty( $recent_posts ) ) {
        return '<p>No posts found.</p>';
    }

    $output = '<ul>';
    foreach ( $recent_posts as $post ) {
        $output .= sprintf(
            '<li><a href="%1$s">%2$s</a></li>',
            esc_url( get_permalink( $post['ID'] ) ),
            esc_html( get_the_title( $post['ID'] ) )
        );
    }
    $output .= '</ul>';

    return $output;
}

register_block_type( 'my-theme/latest-posts-block', array(
    'render_callback' => 'my_theme_render_latest_posts_block',
) );

Explanation:

  • wp_get_recent_posts(): This function retrieves the latest posts from WordPress.
  • render_callback: This PHP function generates the block’s content dynamically and returns it as HTML to be displayed both in the editor and on the front end.

Step 3: Customizing the Block with Attributes

You can enhance the block’s functionality by allowing users to customize the number of posts displayed or other settings. Let’s add a control for adjusting the number of posts.

  1. Modify the JavaScript to Accept Block Attributes

Update your JavaScript file to allow users to set the number of posts via the block settings.

import { registerBlockType } from '@wordpress/blocks';
import { InspectorControls } from '@wordpress/block-editor';
import { PanelBody, RangeControl } from '@wordpress/components';
import ServerSideRender from '@wordpress/server-side-render';

registerBlockType('my-theme/latest-posts-block', {
    title: 'Latest Posts',
    icon: 'list-view',
    category: 'my-custom-category',
    attributes: {
        numberOfPosts: {
            type: 'number',
            default: 5,
        },
    },
    edit: ({ attributes, setAttributes }) => {
        const { numberOfPosts } = attributes;

        return (
            <>
                <InspectorControls>
                    <PanelBody title="Settings">
                        <RangeControl
                            label="Number of Posts"
                            value={numberOfPosts}
                            onChange={(value) => setAttributes({ numberOfPosts: value })}
                            min={1}
                            max={10}
                        />
                    </PanelBody>
                </InspectorControls>
                <ServerSideRender
                    block="my-theme/latest-posts-block"
                    attributes={attributes}
                />
            </>
        );
    },
    save: () => {
        return null; // Server-side block, no content saved
    },
});

Explanation:

  • attributes: We’ve added an attribute called numberOfPosts to control how many posts are displayed.
  • RangeControl: This component provides a slider for users to choose the number of posts (between 1 and 10).
  • InspectorControls: This allows the user to adjust settings in the block’s sidebar.

Step 4: Updating the PHP Render Function to Handle Attributes

Modify the PHP function to use the numberOfPosts attribute and dynamically display the specified number of posts.

function my_theme_render_latest_posts_block( $attributes ) {
    $number_of_posts = isset( $attributes['numberOfPosts'] ) ? $attributes['numberOfPosts'] : 5;

    $recent_posts = wp_get_recent_posts( array(
        'numberposts' => $number_of_posts,
        'post_status' => 'publish',
    ) );

    if ( empty( $recent_posts ) ) {
        return '<p>No posts found.</p>';
    }

    $output = '<ul>';
    foreach ( $recent_posts as $post ) {
        $output .= sprintf(
            '<li><a href="%1$s">%2$s</a></li>',
            esc_url( get_permalink( $post['ID'] ) ),
            esc_html( get_the_title( $post['ID'] ) )
        );
    }
    $output .= '</ul>';

    return $output;
}

register_block_type( 'my-theme/latest-posts-block', array(
    'render_callback' => 'my_theme_render_latest_posts_block',
) );

Explanation:

  • number_of_posts: We’ve updated the function to accept the numberOfPosts attribute and display the appropriate number of posts.

Step 5: Testing the Server-Side Rendered Block

  1. Rebuild Your Block:
    • Run your build command to rebuild the block and ensure it’s loaded properly in the Block Editor.
npm run build
  1. Test in the Editor:
    • Add the Latest Posts block to a post or page in the WordPress Block Editor.
    • Use the sidebar control to adjust the number of posts and observe how the block dynamically updates.
  2. Check Front-End Behavior:
    • Publish the post and verify that the correct number of latest posts is displayed on the front end.

Best Practices for Server-Side Rendered Blocks

  1. Optimize Queries: When fetching data (e.g., posts or metadata), ensure that your queries are optimized to avoid performance issues, especially on high-traffic sites.
  2. Provide User Controls: Allow users to customize the block’s output via attributes, such as setting the number of items displayed or filtering content.
  3. Handle Empty States: Always provide fallback content (e.g., “No posts found”) to handle cases where there is no data to display.

Conclusion: Leveraging Server-Side Rendering for Dynamic Content

Server-side rendered blocks are powerful tools for dynamically displaying content in WordPress. Whether you’re pulling in posts, custom data, or external APIs, these blocks ensure that content is always up to date, both in the editor and on the front end. This approach is particularly useful for real-time data or frequently changing content like recent posts, latest products, or any type of dynamic feed.

In this article, you’ve learned how to:

  • Create a basic server-side rendered block using the ServerSideRender component.
  • Fetch dynamic content from WordPress using the render_callback function in PHP.
  • Customize the block by adding user-configurable attributes.
  • Test server-side blocks both in the editor and on the front end.

In Day 18, we’ll explore custom block transforms, which allow you to convert one block type into another, giving users more flexibility when editing content.


Leave a Reply

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