Skip to main content

Fetching Data with useContent / getContent

Overview

This documentation will explain how to use useContent and getContent to fetch data.

  • useContent: React hook for client-side content fetching with automatic state management
  • getContent: Server-side function for content fetching during server rendering or static site generation

Method Comparison

FeatureuseContentgetContent
EnvironmentReact Components (Client)Server-side (e.g., Next.js getServerSideProps)
State ManagementAutomatic (loading, error states)Manual handling required
Use CasesInteractive search, real-time updatesPre-rendered pages, static site generation
SEO BenefitsLimited (loads after initial render)Enhanced (content available at initial load)

Definitions

useContent

  • Purpose: Fetches content on the client side within React components.
  • Usage Environment: Client-side rendering (CSR).
  • Automatic State Management: Handles loading, success, and error states internally.
  • Syntax:
const { payload, error, state } = useContent(
id, // Content ID (string)
path?, // Content path (string, optional)
options? // Additional options (object, optional)
);

getContent

  • Purpose: Fetches content on the server side during SSR or SSG.
  • Usage Environment: Server-side rendering (SSR), static site generation (SSG).
  • Manual State Handling: Requires explicit error and loading state management.
  • Syntax:
    const { payload, error } = await getContent(
    id, // Content ID (string)
    path?, // Content path (string, optional)
    options? // Additional options (object, optional)
    );

When to Use useContent

  • Fetching data in response to user interactions.
  • Loading additional content without a full page reload.
  • Components that depend on client-side state or effects.
  • Real-time updates and dynamic content rendering.

When to Use getContent

  • Fetching data during server-side rendering or static site generation.
  • Pre-rendering pages with dynamic content for SEO benefits.
  • Providing fully-rendered content at initial page load.
  • Fetching content that doesn't change frequently.

Tips and Best Practices

  • Use the Appropriate Method: Choose useContent for client-side interactions and getContent for server-side data fetching.
  • Optimize Performance: -- Server-Side: Fetch only the necessary data to render the page. -- Client-Side: Avoid unnecessary re-renders by managing state effectively.
  • Cache Content: Implement caching strategies for server-side data to reduce load times.
  • Preview Mode: Utilize the resourceVersion option to fetch draft content during content previews.
  • Error Logging: Log errors for monitoring and debugging purposes.

Client-Side Fetching with useContent

import React from "react";
import { useContent } from "@your-org/cms-integration";

function Article({ articleId }) {
const { payload: content, error, state } = useContent(articleId);

if (state === "loading") return <p>Loading...</p>;
if (error) return <p>Error loading content: {error.message}</p>;

return (
<article>
<h1>{content.title}</h1>
<div>{content.data.body}</div>
</article>
);
}

Note

  • Automatic State Management: state indicates the current state ('loading', 'success', 'error').
  • Error Handling: Check the error object to handle any issues during fetching.
  • Reactivity: The component re-renders when the content is fetched.

Server-Side Fetching with getContent

import { GetServerSideProps } from "next";
import { getContent } from "@your-org/cms-integration";

export const getServerSideProps: GetServerSideProps = async ({ params }) => {
const id = params?.id as string;
const { payload: content, error } = await getContent(id);

if (error || !content) {
return { notFound: true };
}

return {
props: { content },
};
};

function ArticlePage({ content }) {
return (
<article>
<h1>{content.title}</h1>
<div>{content.data.body}</div>
</article>
);
}

export default ArticlePage;

Note

  • Manual State Handling: Must check for errors and handle them appropriately.
  • SEO Benefits: Content is available at initial load, improving SEO.
  • Error Handling: If content is not found, return notFound: true to render a 404 page.

Response Types

Both useContent and getContent return a response object with the following structure:

  payload?: T;
error?: Error;
state?: 'loading' | 'success' | 'error';
}

interface Content {
id: string;
title: string;
status?: boolean;
author?: string;
data: Record<string, unknown>;
}

Note

  • payload: The fetched content data.
  • error: An error object if the fetching fails.
  • state (useContent only): Indicates the current state of the fetch operation.

Client-Side Fetching

Basic useContent Usage

const { payload, error, state } = useContent(
id, // Content ID (string)
path?, // Content path (string, optional)
options? // Additional options (object, optional)
);

Fetching Content with Dynamic Updates

import React, { useState } from "react";
import { useContent } from "@your-org/cms-integration";

function ContentLoader() {
const [contentId, setContentId] = useState("1");
const { payload, error, state } = useContent(contentId);

if (state === "loading") return <p>Loading...</p>;
if (error) return <p>Error: {error.message}</p>;

return (
<div>
<article>
<h1>{payload.title}</h1>
<div>{payload.data.body}</div>
</article>
<button onClick={() => setContentId("2")}>Load Content 2</button>
</div>
);
}

Server-Side Fetching

Basic getContent Usage

export async function getServerSideProps() {
const { payload: content, error } = await getContent("content-id");

if (error || !content) {
return { notFound: true };
}

return {
props: {
content,
},
};
}

Common Patterns

Fetching Content by Path

// Using useContent
const { payload, error } = useContent("", "/path/to/content");

// Using getContent
const { payload, error } = await getContent("", "/path/to/content");

Advanced Usage

Fetching Related Content

function Article({ articleId }) {
const { payload: article, error, state } = useContent(articleId);

if (state === "loading") return <p>Loading article...</p>;
if (error) return <p>Error loading article: {error.message}</p>;

const relatedContentIds = article.data.relatedContentIds || [];

return (
<div>
<h1>{article.title}</h1>
<div>{article.data.body}</div>

<h2>Related Content</h2>
{relatedContentIds.map((id) => (
<RelatedContent key={id} contentId={id} />
))}
</div>
);
}

function RelatedContent({ contentId }) {
const { payload: content, error, state } = useContent(contentId);

if (state === "loading") return <p>Loading related content...</p>;
if (error) return <p>Error loading related content: {error.message}</p>;

return (
<div>
<h3>{content.title}</h3>
<p>{content.data.summary}</p>
</div>
);
}

Using Options for Preview Mode

function PreviewArticle({ articleId }) {
const {
payload: content,
error,
state,
} = useContent(articleId, undefined, {
resourceVersion: "draft",
isPreview: true,
});

if (state === "loading") return <p>Loading preview...</p>;
if (error) return <p>Error loading preview: {error.message}</p>;

return (
<article>
<h1>{content.title} (Preview)</h1>
<div>{content.data.body}</div>
</article>
);
}

Error Handling Patterns

Using Try-Catch with getContent

export const getServerSideProps: GetServerSideProps = async ({ params }) => {
try {
const id = params?.id as string;
const { payload: content } = await getContent(id);

if (!content) {
return { notFound: true };
}

return {
props: { content },
};
} catch (error) {
console.error("Error fetching content:", error);
return { notFound: true };
}
};

Handling Errors in useContent

function ContentComponent({ contentId }) {
const { payload, error, state } = useContent(contentId);

if (state === "loading") return <p>Loading...</p>;

if (error) {
console.error("Error fetching content:", error);
return <p>An error occurred while loading content.</p>;
}

return (
<div>
<h1>{payload.title}</h1>
<p>{payload.data.body}</p>
</div>
);
}