Next.js server components and live preview #50360
Unanswered
bm-vs
asked this question in
App Router
Replies: 2 comments 3 replies
-
Hey @BSantos22, did you ever find a good solution for this? I'm running into the same thing now wondering if you made any progress outside of this discussion. |
Beta Was this translation helpful? Give feedback.
3 replies
-
I don't know if it's what your looking for, but what I'm doing right now is moving all off the queries on server components and conditionally call different queries/endpoints (and different cache-settings), based on the // page.tsx
const Page = async ({
params,
}: {
params: { tour: string };
}) => {
const { isEnabled } = draftMode();
let props;
if (isEnalbed){
props = fetch('draftEndPointAndVariables',{ cache: 'no-store' })
} else {
props = fetch('prodEndpoitAndVariables')
}
const page = <PageComponent props={props}/>
if (isEnabled){
return <PreviewWrapper page={page}/>
} else {
return page
}
} 'use client';
import React, { useEffect } from 'react';
import { useRouter } from 'next/navigation';
const PreviewWrapper: React.FC<{ page: React.ReactNode }> = ({ page }) => {
const router = useRouter();
useEffect(() => {
setInterval(() => {
router.refresh();
}, 10000);
});
return page;
};
export default PreviewWrapper; |
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
I'm migrating a website to use the Next.js app/ directory and ran into some issues.
I'm using Sanity as the CMS for the website.
To render a component that requires fetching data I use 3 components: a server (entry point) component, a client (draft) component and a render component.
The server component is the entry point. It uses the draftMode() utility function.
If draft mode is disabled, it fetches the data that is needed and passes it to the render component. For example, fetching all of the content of a page.
Otherwise, it hands control over to the client component.
The client component uses usePreview to fetch the data and passes it to the render component.
The render component is just a dumb component that receives data and renders it. It inherits the render context of its parent, so it's a Client Component when included by the draft component, and a Server Component when rendered by the entry point component.
Since it can be used in both contexts, both using server specific things like draftMode() and client specific things like useState() fails.
This pattern works well at the page level, but starts to have problems with nesting.
For example, including an ArticleList section that fetches the articles for itself inside of a Page.
How can the ArticleList component figure out if it's in draft mode or not? It's possible that it's being used either as a Client Component or as a Server Component.
The trivial solution is to use props, since that works both for Server Components and Client Components. But that doesn't scale very well. If there are multiple levels of components that fetch data, then I have to propagate isEnabled from draftMode() all the way from the last component that is exclusively a Server Component - the Page.
draftMode() can't be used, since that only works in the context of the server.
useContext is also excluded, since that only works on the client.
Another solution is to wrap window in a try/catch. This is what I'm doing and that seems to work well but also feels like a very hacky thing to do.
Is there any alternative approach to doing this? Is there anything that I'm missing?
Here's some code if it makes more sense:
page.tsx
page.draft.tsx
page.render.tsx
article-list-all.tsx
article-list-all.draft.tsx
article-list-all.render.tsx
https://gist.github.com/BSantos22/85260e5129ad0ce1805202761644e626
Beta Was this translation helpful? Give feedback.
All reactions