NextJS 13 with App Router, I have the following:
/src/app/blog/[...slug].js
const getArticleDetails = async (slug) => {
const response = builder
.get('blog-article', {
prerender: false,
options: { includeRefs: true },
query: {
'data.urlSlug': `/blog/${slug}`,
},
})
.toPromise();
return response;
};
const BlogArticleDetailPage = async (props) => {
const { slug } = props.params;
const fullPath = slug.join('/');
const article = await getArticleDetails(fullPath);
return (
<main>
<BlogArticleLayout
blogArticle={article}
/>
</main>
);
}
/src/components/BlogArticleLayout.js
function BlogArticleLayout({ blogArticle }) {
return (
<BuilderContent
model="blog-article"
content={blogArticle}
options={{ includeRefs: true }}>
{(data, isLoading, fullData) => {
return (
<h1>{data.title}</h1>
{/* ...other components that render off of `data` */}
<BuilderComponent content={fullData} model="blog-article" />
);
}}
</BuilderContent>
);
}
Scenario: all of the components/elements within BuilderContent are rendering perfectly as expected. The data is updated in Preview as I update them.
However, when I add BuilderComponent to also display the Drag + Drop content, it goes into a cycle of endlessly refreshing/rehydrating.
I’m sure this must be some incorrect combination of sorts. I just can’t find the correct combo.
Additional context. If I don’t add options={{ includeRefs: true }}
it also works without the endless refresh, but of course, it doesn’t update my nested refs when I make changes.
Hi @brucewyne,
Could you try to pass enrich
in the options? I believe that should help with getting the updated nested refs.
options: {
enrich: true,
}
Some reference code snippet:
export async function getStaticProps({
params
}: GetStaticPropsContext<{ slug: string[] }>) {
const articleData =
(await builder
.get('article',{
options: {
enrich: true,
},
query:{
'data.slug': params?.slug
}
}).toPromise()) || null;
const articleTemplate = await builder
.get('blog', {
}).toPromise();
return {
props: {
articleData,
articleTemplate,
},
revalidate: 5,
};
}
export async function getStaticPaths() {
const articles = await builder.getAll('article', {
options: {noTargeting: true},
omit: 'data.blocks'
})
articles.map(article => console.log(`/blog/${article.data?.slug}`),)
return {
paths : articles.map(article => `/blog/${article.data?.slug}`),
fallback: true,
};
}
export default function Page({
articleTemplate ,
articleData
}:InferGetStaticPropsType<typeof getStaticProps>) {
const router = useRouter();
if (router.isFallback) {
return <h1>Loading...</h1>;
}
const isLive = !Builder.isEditing && !Builder.isPreviewing;
if (!articleData && isLive) {
return (
<>
<Head>
<meta name="robots" content="noindex" />
<meta name="title"></meta>
</Head>
<DefaultErrorPage statusCode={404} />
</>
);
}
return (
<>
<Head>
<meta name="viewport" content="width=device-width, initial-scale=1" />
{!articleData && <meta name='robots' content='noindex'/>}
</Head>
<BuilderComponent model="blog"
content={articleTemplate}
data={{article: articleData?.data}}
/>
</>
);
}
Regarding the endless refreshing when add the builderComponent , it will be helpful if you could share a recording of the issue with the steps performed?
I would like to examine this further, thank you for reaching out!
Here’s an example for reference.
Loom | Free Screen & Video Recording Software | Loom - here’s a live demo. As far as I can tell, most of what I have here follows the example.
In this video, I do pass props.blogArticle
to the BuilderComponent rather than fullContent
from the BuilderContent component. However I’ve tried it both ways and it doesn’t make a difference.
Hi @brucewyne !
I have a couple of questions regarding your setup:
- SDK Version: Could you please let me know which version of the SDK you are currently using? If possible, consider updating to the latest version.
- Purpose of : I’m curious about the purpose of using
<BuilderContent/>
. Is it primarily for enabling live editing of custom input fields?
If updating the SDK doesn’t resolve the issue you’re facing, here are a couple of alternative approaches you can consider:
Option 1 (Passing blogArticle data to content instead of fullData):
/src/components/BlogArticleLayout.js
function BlogArticleLayout({ blogArticle }) {
return (
<BuilderContent
model="blog-article"
content={blogArticle}
options={{ includeRefs: true }}>
{(data, isLoading, fullData) => {
return (
<h1>{data.title}</h1>
{/* ...other components that render off of `data` */}
<BuilderComponent content={blogArticle} model="blog-article" />
);
}}
</BuilderContent>
);
}
Option 2 (Moving outside of ):
/src/components/BlogArticleLayout.js
function BlogArticleLayout({ blogArticle }) {
return (
<BuilderContent
model="blog-article"
content={blogArticle}
options={{ includeRefs: true }}>
{(data, isLoading, fullData) => {
return (
<h1>{data.title}</h1>
{/* ...other components that render off of `data` */}
);
}}
</BuilderContent>
<BuilderComponent content={blogArticle} model="blog-article" />
);
}
I hope this helps! Let me know if you have any further questions or if there’s anything else I can assist you with.