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 managementgetContent
: Server-side function for content fetching during server rendering or static site generation
Method Comparison
Feature | useContent | getContent |
---|---|---|
Environment | React Components (Client) | Server-side (e.g., Next.js getServerSideProps ) |
State Management | Automatic (loading, error states) | Manual handling required |
Use Cases | Interactive search, real-time updates | Pre-rendered pages, static site generation |
SEO Benefits | Limited (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>
);
}