Logo

dev-resources.site

for different kinds of informations.

Render Block component in Next JS and Headless CMS

Published at
10/26/2024
Categories
headlesscms
nextjs
jsx
Author
aswanth_raveendranek_a2a
Categories
3 categories in total
headlesscms
open
nextjs
open
jsx
open
Author
24 person written this
aswanth_raveendranek_a2a
open
Render Block component in Next JS and Headless CMS

Introduction

In modern web development, creating dynamic and scalable websites is essential for delivering personalized user experiences. One of the most effective ways to achieve this is by integrating a headless CMS with a frontend framework like Next.js. A headless CMS allows developers to separate the content management layer from the presentation layer, enabling seamless content updates without touching the codebase. This setup is ideal for sites that require frequent content changes, like blogs, portfolios, and e-commerce sites.

The Role of Headless CMS

A headless CMS (Content Management System) is a backend-only system that manages content independently of the frontend. This approach allows developers to select or build a frontend framework without being constrained by the CMSโ€™s native capabilities. Popular headless CMS options includes Strapi, Payload etc.
With a headless CMS, content creators and developers can work in parallel: editors manage content, and developers focus on the presentation layer using tools like Next.js.
NB: You don't need to know more about CMS to create this. Just understand about the APIs your CMS framework provides.

Set Up

Create a component called renderBlocks in your Next JS src folder.

Folder structure

Now create a functional component

import type { Page } from "@/types/block-types/types";
import React, { Fragment } from "react";
import HeroBanner from "./blocks/HeroBanner";
import FormBlock from "./blocks/FormBlock";

const blockComponents = {
    banner: HeroBanner,
    formBlock: FormBlock
};

interface RenderBlocksProps {
  blocks: Page["layout"];
}

export const RenderBlocks: React.FC<RenderBlocksProps> = (props) => {

};
Enter fullscreen mode Exit fullscreen mode

The blockComponents object contain the Components that we created in our project.

The component will accept a prop called blocks which is the API response of the CMS which includes all the data that needs to show in the page.

Below is an example type of blocks

export interface Page {
    layout: (BannerBlock | FormBlock)[];
}

export interface BannerBlock {
    media: {
        src: string;
        alt: string;
    };
    title: string;
    blockType: "banner"
}

export interface FormBlock {
    title: string;
    blockType: "formblock"
}
Enter fullscreen mode Exit fullscreen mode

You can create a file called block-types.ts in the utils folder and create your types for blocks there.
NB: This types can be changed according to the CMS you use and also it depends on the field name that you use in your CMS.

In the blocks props you will have array of objects each object is the data that you want to show in your page. And each object contain a unique property. I mentioned it here as blockType. This blockType should be the same key of the blockComponents object.

Below is a mock data that you are going to get from your CMS API. This will have changes from an actual response. I am just showing it here for better understanding.

{
  layout: [
    {
      image: {
        src: "image.png",
        alt: "Alt text",
      },
      title: "Banner Title",
      blockType: "banner",
    },
    {
      title: "Contact Form",
      blockType: "formBlock"
    }
  ]
};
Enter fullscreen mode Exit fullscreen mode

Below is the complete code for your renderBlocks component

import type { Page } from "@/types/block-types/types";
import React, { Fragment } from "react";
import HeroBanner from "./blocks/HeroBanner";
import FormBlock from "./blocks/FormBlock";

const blockComponents = {
    banner: HeroBanner,
    formBlock: FormBlock
};

interface RenderBlocksProps {
  blocks: Page["layout"];
}

export const RenderBlocks: React.FC<RenderBlocksProps> = (props) => {
  const { blocks } = props;

  const hasBlocks = blocks && Array.isArray(blocks) && blocks.length > 0;

  if (hasBlocks) {
    return (
      <Fragment>
        {blocks.map((block, index) => {
          const { blockType } = block;

          if (blockType && blockType in blockComponents) {
            const Block = blockComponents[blockType];

            if (Block) {
              return (
                <div key={index}>
                  {/* @ts-expect-error: has no properties in common with type 'IntrinsicAttributes' */}
                  <Block {...block} />
                </div>
              );
            }
          }
          return null;
        })}
      </Fragment>
    );
  }

  return null;
};

Enter fullscreen mode Exit fullscreen mode

How to use this?
Create a page in your app directory and call the render blocks components there with data you fetched from the CMS API.

import { Page } from "@/types/block-types/types";
import { RenderBlocks } from "@/component/RenderBlocks";

const HomePage= async() => {
cons page:Page = await CallToPageDataAPI()
  return (
    <div className="bg-background">
      <RenderBlocks blocks={page.layout} />
    </div>
  );
};

export default HomePage;
Enter fullscreen mode Exit fullscreen mode

The logic presented here is tailored to my specific use case, but feel free to adapt it as needed. If you encounter any issues or have suggestions, please don't hesitate to leave a comment. I'm always open to feedback and improvement. Thank you for taking the time to read this!

NB: A CMS API response will be more complex than what is referred to here. Please make necessary changes to the types according to your use case.

jsx Article's
30 articles in total
Favicon
Why JSX/TSX Isn't Cool
Favicon
Building Static HTML Pages with JSX Server-Side Rendering
Favicon
Task completed
Favicon
Why React Can Surprise You (And How to Tame It)
Favicon
Render Block component in Next JS and Headless CMS
Favicon
Full Guide For React Developer
Favicon
Imagining React Without JSX: A Developer's Worst Nightmare
Favicon
Projeto de Integraรงรฃo: FastAPI, Jinja2 e JSX
Favicon
Introducing Brisa: Full-stack Web Platform Framework ๐Ÿ”ฅ
Favicon
Understanding JSX in React
Favicon
How React JSX Gets Transformed Into JavaScript Behind the Scenes
Favicon
Day 3: Understanding JSX and Rendering Elements - ReactJS
Favicon
A Comprehensive Guide to Writing JSX in React (with Vite)
Favicon
{useState} HooK { Briefly Explained};
Favicon
Build Reactive Web Components with SSR
Favicon
JSX Limitations and Best Practices in React
Favicon
Making headless components easy to style
Favicon
React HooK= { Briefly Explained};
Favicon
How JSX Works
Favicon
Everything About JSX Syntax And Its Basics: A Quick Guide
Favicon
Converting Extension from JS to JSX
Favicon
Mastering JSX Editing in Emacs with Tree-sitter
Favicon
Building a dynamic Canvas rendering engine using JSX
Favicon
Comprendre les Props en React.js
Favicon
iconSvg
Favicon
An 85 Lines of Code Static Site Generator with Bun and JSX
Favicon
Can use React Smooth Scroll package and React Router Links on the same website?
Favicon
Dynamic background image loading
Favicon
How to render JSX to whatever you want with a custom JSX Renderer
Favicon
CREATE A LIBRARY WITH JSX & CUSTOM STATE

Featured ones: