NextJS: How do I statically render a page, but then update with user-specific information once rendered

52 Views Asked by At

I'm after some guidance on a particular data fetching use-case with NextJS static page rendering. We have a page that displays articles (imagine something like this page). The data is the same for everyone (and so would be a good candidate to render statically), except lock icons show on the articles if you don't have permission to view them. The UX/loading sequence I'm ideally looking for would be:

  • Statically render the page
  • Fetch the user-specific data, and render the lock icons accordingly. So you'd see them appear after loading.

We would typically fetch the data for the whole page in one query (we use graphQL), so I’d like to avoid a solution such as firing off additional data requests from each lock icon.

Has anyone tried to achieve something similar? I was thinking something like the below could work (although seems odd):

// We use Relay/GraphQL, but in theory I think this could be any data fetching solution
const PageQuery = grapqhl`.....`

export const getStaticProps = ....fetch PageQuery

const Page = ({data: staticData, ...otherProps}) => {
    const {data: clientFetchedData} = useQuery(PageQuery) // this means the clients will request the data again upon loading
    const data = clientFetchedData || staticData
    
    // Now can pass data down to any sub-component
}

I think the drawback here is that with Next13, this would need to be a client component. And because you can't pass props from client -> server components, it would mean the whole page would need to be a client component.

Are there any good patterns here? It's possible those outside of the Relay community have figured out a way of doing this, so would be great to hear of any generalised solutions.

1

There are 1 best solutions below

1
Explorer On

Use middleware to restrict access to your statically generated pages. Depending on the user auth state, you can either return the page or return the lock icon.