Component-level data fetching in JSS Next.js apps
Next.js can pre-render pages at build time or on each request using page-level data fetching strategies for each pre-rendering form.
If you want to fetch component-specific data at the component level, you can use a mechanism similar to page-level data fetching, by implementing and exporting the getStaticProps
function for static generation (SG), or the getServerSideProps
function for server-side rendering (SSR).
Do not include secrets or sensitive information in component-level getStaticProps
and getServerSideProps
functions. These functions are included in the client-side bundle. Also included in the client bundle are any imports the functions depend on, even if the client-side code does not use the imports.
This does not affect page-level getStaticProps
and getServerSideProps
functions.
The SitecorePagePropsFactory
class uses an instance of the ComponentPropsService
class that helps identify which components require data retrieval. The ComponentPropsService
is provided by the NPM package @sitecore-jss/sitecore-jss-nextjs
.
The ComponentPropsService class
The ComponentPropsService
accepts the following parameters:
-
componentModule
- a function returning a Next.js component using thecomponentName
argument. ThecomponentModule
function definition is in the filesrc/temp/componentFactory
. If not present, generate it by runningscripts/bootstrap.ts
. -
layoutData
- Layout Service data for your page. -
context
- The Next.js SSG or SSR context.
The ComponentPropsService
traverses the layout service data and looks at all the renderings. To find the components that require data fetching, the service spies on the component using the rendering.componentName
against the list of component registrations in the src/temp/componentFactory
file.
If the component defines and exports the functions getStaticProps
or getServerSideProps
, the ComponentPropsService
runs the function. After applying all side-effects, it stores the component data in a componentProps
object in the format { [rendering.uid]: data }
.
For example, the following component defines a data fetching function and accesses the component data with the help of useComponentProps
and the rendering.uid
.
This example component contains an implementation of both getStaticProps
and getServerSideProps
. In a real component, you must define only one, depending on your chosen rendering mode.
import {
Text,
RichText,
Field,
GetServerSideComponentProps,
GetStaticComponentProps,
useComponentProps,
ComponentRendering,
} from '@sitecore-jss/sitecore-jss-nextjs';
type PostEntity = {
title: string;
body: string;
};
type ContentBlockProps = {
rendering: ComponentRendering;
fields: {
heading: Field<string>;
content: Field<string>;
};
};
const ContentBlock = ({ fields, rendering }: ContentBlockProps): JSX.Element => {
const externalData = rendering.uid ? useComponentProps<PostEntity>(rendering.uid) : undefined;
return (
<>
<Text tag="h2" className="display-4" field={fields.heading} />
<RichText className="contentDescription" field={fields.content} />
{externalData && (
<div>
<h1>{externalData?.title}</h1>
<p>{externalData?.body}</p>
</div>
)}
</>
);
};
const fetchPost = () =>
fetch('https://jsonplaceholder.typicode.com/posts/1').then((res) => res.json());
export const getStaticProps: GetStaticComponentProps = async (rendering, layoutData, context) => {
const post = await fetchPost();
return post;
};
export const getServerSideProps: GetServerSideComponentProps = async (rendering, layoutData) => {
const post = await fetchPost();
return post;
};
export default ContentBlock;