I started building a Next.js frontend for a WordPress website, using the App Router and GraphQL plugin to fetch data from WordPress. The homepage is all set up to display the latest posts, and it's a server component.
import PostCard from "./components/post";
import styles from './page.module.scss'
interface Post {
title: string;
date: string;
excerpt: string;
featuredImage: {
node: {
sourceUrl: string;
};
};
categories: {
edges: {
node: {
name: string;
};
}[];
};
slug: string;
author: {
node: {
name: string;
};
};
}
async function getPosts(cursor: string): Promise<Post[]> {
const endpoint = process.env.WORDPRESS_API_URL || '';
const response = await fetch(endpoint, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
query: `
query GetPosts($cursor: String!) {
posts(first: 10, after: $cursor) {
nodes {
title
date
excerpt
featuredImage {
node {
sourceUrl
}
}
categories {
edges {
node {
name
}
}
}
slug
author {
node {
name
}
}
}
}
}
`,
variables: {
cursor: cursor,
},
}),
});
const data = await response.json();
return data.data.posts.nodes;
}
export default async function HomePage() {
const posts = await getPosts("");
return (
<div>
<div className={styles.postsList}>
{posts.map((post) => (
<PostCard post={post} key={post.slug}/>
))}
</div>
<button onClick={ }>Load More</button>
</div>
);
}
The challenge is loading the next batch of posts right after this cursor (which is ID of the last post I loaded by GraphQL) without using React's useState
or useEffect
hooks, as these do no work on server components.
How can I make the "Load More" button work with server components?
I've tried to tackle pagination using query strings, but that plan fizzled out because GraphQL's WordPress plugin exclusively works with cursor-based pagination.