Creating a BlockRenderer component

Note: The example below assumes you have a paragraph block added to the homepage in WordPress.

Creating a <BlockRenderer /> component is the recommended way to render WordPress block data within your Astro project. We can use the .map render function from the previous section and replace it with a new <BlockRenderer /> component. We can also import the BlockRenderer into itself as a BlockRendererInner component to render any innerBlocks belonging to a particular block. First create a <BlockRenderer /> component:

// src/components/BlockRenderer.astro
---
import BlockRendererInner from "./BlockRenderer.astro";
import type { Block } from "@wp-block-tools/styles";
import { getBlockStyling } from "@wp-block-tools/styles";
type Props = {
  blocks: Block[]
};
const { blocks } = Astro.props;
---
{blocks.map((block) => {
  const { styles, classes } = getBlockStyling(block);
  switch(block.name){
    case "core/template-part":
      return <BlockRendererInner blocks={block.innerBlocks} />;
    case "core/post-content":
      return (
        <div class={classes} style={styles}>
          <BlockRendererInner blocks={block.innerBlocks} />
        </div>
      );
    case "core/paragraph":
      return <p set:html={block.attributes?.content} class={classes} style={styles} />
    default:
      return null;
  }
})}

Then update the index page:

// src/pages/index.astro
---
import { BlockRenderer } from "../components/BlockRenderer.astro";
import { getBlockStyling } from "@wp-block-tools/styles";
import type { Block } from "@wp-block-tools/styles";

const response = await fetch(`${import.meta.env.WPGRAPHQL_URL}`, {
  method: "POST",
  headers: {
    "content-type": "application/json"
  },
  body: JSON.stringify({
    query: `
      query PageData {
        cssVariables
        nodeByUri(uri: "/"){
          ... on ContentNode {
            blocks
          }
        }
      }
    `
  })
});

const {
  data: {
    cssVariables,
    nodeByUri
  }
} = await response.json();
const blocks: Block[] = nodeByUri?.blocks ?? [];
---
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width" />
    <meta name="generator" content={Astro.generator} />
    <title>Homepage</title>
    {!!cssVariables && <style set:html={`:root{${cssVariables}}`} />}
  </head>
  <body>
    <BlockRenderer blocks={blocks} />
    {blocks.map((block) => {
      const { styles, classes } = getBlockStyling(block);
      switch(block.name){
        case "core/paragraph":
          return <p set:html={block.attributes?.content} class={classes} style={styles} />
        default:
          return null;
      }
    })}
  </body>
</html>