1

I want to render a static listing with cached HTML on initial page load using data that was fetched server side.

I do NOT want to display a loading indicator on initial page load. I want to display cached HTML data that was fetched on the server, not in browser.

HOWEVER I also want RTK Query to be able to handle updates to the list data if the list data is updated.

At the moment, I have this code:

app/discussions/page.tsx

import { DiscussionList } from '../components/DiscussionList'

export default async function DiscussionListPage() {
    return <DiscussionList />
}

app/components/DiscussionList.tsx

export function DiscussionList() {
    const { data, isFetching } = useFetchDiscussionsQuery()

    if (isFetching) {
        return <p>Loading...</p>
    }

    return (
        <ul>
            {data?.map((item) => (
                <li key={item.discussionId}>
                    <h2>{item.title}</h2>
                    <p>{item.body}</p>
                </li>
            ))}
        </ul>
    )
}

This displays a loading indicator in the static HTML at the moment, not prefetched data.

I need to change it so it renders list items on page load instead of the loading indicator.

1 Answer 1

1

This was the solution I came up with:

app/discussions/page.tsx

'use server'

export default async function DiscussionListPage() {
    // Next.js will cache the result of this server-side fetch request
    const response = await fetch('http://localhost:3000/discussions', {
        // set up for on-demand server cache invalidation
        next: { tags: ['discussions'] },
    })
    const data = await response.json()

    // Feed the server fetched data into DiscussionList as a prop
    return <DiscussionList ssrData={data} />
}

app/components/DiscussionList.tsx

'use client'

interface DiscussionListProps {
    ssrData: Array<Discussion> | undefined
}

export function DiscussionList({ ssrData }: DiscussionListProps) {
    const { data, isFetching } = useFetchDiscussionsQuery()

    // While RTK Query is being fetched, use the SSR discussions data
    const finalData = data || ssrData || []

    return (
        <ul>
            // Indicating to the user that new data is being fetched
            // so the list might change
            {isFetching && <li>Updating list...</li>}
            {finalData.map((item) => (
                <li key={item.discussionId}>
                    <h2>{item.title}</h2>
                    <p>{item.body}</p>
                </li>
            ))}
        </ul>
    )
}

Use on-demand revalidation to invalidate the cache when appropriate.

'use server'
 
import { revalidateTag } from 'next/cache'
 
export default async function action() {
  revalidateTag('collection')
}
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.