Using Experiences with NextJS
Table of contents
Using pages router
Server-side rendering using pages router
When using pages router in NextJS, you can render your experience on the server.
Important:
- Use the vanilla JS fetchers (
fetchBySlug
orfetchById
) inside of the server side methods (getServerSideProps
orgetStaticProps
) instead of the React hooksuseFetchBySlug
oruseFetchById
. - The
experience
object returned by the fetchers is not serializable by NextJS directly due to their strict JSON serialization techniques. Therefore, we need to serialize theexperience
ourselves and pass the JSON string as a prop to the component. - In the component, we need to recreate the
experience
object from the JSON string by passing it to thecreateExperience
function.
Below is an example page using NextJS SSR in the pages router:
import { createClient } from 'contentful';
import {
fetchBySlug,
ExperienceRoot,
createExperience,
} from '@contentful/experiences-sdk-react';
import { GetServerSidePropsContext, InferGetServerSidePropsType } from 'next';
const accessToken = process.env.NEXT_PUBLIC_CTFL_ACCESS_TOKEN!;
const space = process.env.NEXT_PUBLIC_CTFL_SPACE!;
const environment = process.env.NEXT_PUBLIC_CTFL_ENVIRONMENT!;
const experienceTypeId = process.env.NEXT_PUBLIC_CTFL_EXPERIENCE_TYPE!;
const localeCode = 'en-US';
const client = createClient({
space,
environment,
accessToken,
});
function MyPage({
experienceJSON,
}: InferGetServerSidePropsType<typeof getServerSideProps>) {
//Recreate the experience object from the serialized JSON
const experience = createExperience(experienceJSON);
return (
<main style={{ width: '100%' }}>
<ExperienceRoot experience={experience} locale={'en-US'} />
</main>
);
}
export const getServerSideProps = async ({}: GetServerSidePropsContext) => {
const experience = await fetchBySlug({
client,
slug: 'homePage', //could be fetched from the context
experienceTypeId,
localeCode,
});
//Serialize the experience manually
const experienceJSON = JSON.stringify(experience);
return {
props: {
experienceJSON: experienceJSON,
},
};
};
export default MyPage;
Client-side rendering using pages router
When using client side rendering, fetching and displaying an experience is similar to how it is done in a normal single page application.
import React from 'react';
import { createClient } from 'contentful';
import {
ExperienceRoot,
useFetchBySlug,
} from '@contentful/experiences-sdk-react';
const accessToken = process.env.NEXT_PUBLIC_CTFL_ACCESS_TOKEN!;
const space = process.env.NEXT_PUBLIC_CTFL_SPACE!;
const environment = process.env.NEXT_PUBLIC_CTFL_ENVIRONMENT!;
const experienceTypeId = process.env.NEXT_PUBLIC_CTFL_EXPERIENCE_TYPE!;
const localeCode = 'en-US';
const client = createClient({
space,
environment,
accessToken,
});
const MyComponent: React.FC = (props) => {
const { experience, isLoading, error } = useFetchBySlug({
client,
slug: 'homePage', //Could be fetched from the url,
experienceTypeId: experienceTypeId,
localeCode,
});
if (isLoading) return <div>Loading...</div>
if(error) return <div>Error: {error.message}</div>
return <ExperienceRoot experience={experience} locale={localeCode} />;
};
export default MyComponent;
Using app router
Server-side rendering using app router
Currently, Experiences don't support server-side rendering using the app router in NextJS. We are looking into fixing this in an upcoming release. For now, your experience must be rendered client side.
Client-side rendering using app router
When using client-side rendering, fetching and displaying an experience is similar to how it is done in a normal single page application, except you add the 'use client' directive at the top of the component:
'use client';
import React from 'react';
import { createClient } from 'contentful';
import { ExperienceRoot, useFetchBySlug } from '@contentful/experiences-sdk-react';
const accessToken = process.env.NEXT_PUBLIC_CTFL_ACCESS_TOKEN!;
const space = process.env.NEXT_PUBLIC_CTFL_SPACE!;
const environment = process.env.NEXT_PUBLIC_CTFL_ENVIRONMENT!;
const experienceTypeId = process.env.NEXT_PUBLIC_CTFL_EXPERIENCE_TYPE!;
const localeCode = 'en-US';
const client = createClient({
space,
environment,
accessToken,
});
const MyComponent: React.FC = (props) => {
const { experience, isLoading, error } = useFetchBySlug({
client,
slug: 'homePage', //Could be fetched from the url,
experienceTypeId: experienceTypeId,
localeCode,
});
if (isLoading) return <div>Loading...</div>;
if (error) return <div>Error: {error.message}</div>;
return <ExperienceRoot experience={experience} locale={localeCode} />;
};
export default MyComponent;