我开始为WordPress网站构建一个Next.js前端,使用应用程序路由和GraphQL插件从WordPress获取数据.主页全部设置为显示最新帖子,并且它是一个服务器组件.

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>
    );
}

挑战是在不使用React的useStateuseEffect钩子的情况下加载紧跟在该游标之后的下一批帖子(这是我由GraphQL加载的最后一篇帖子的ID),因为这些钩子不会在服务器组件上工作.

如何使"加载更多"按钮与服务器组件一起工作?

我曾try 过使用查询字符串进行分页,但这个计划以失败告终,因为GraphQL的WordPress插件只支持基于指针的分页.

推荐答案

Server components and client components can be combined in the same component tree,这就是您在这里应该做的:将服务器部分和客户端部分分离在两个独立的组件中.

您发布的大部分内容都是服务器部分,并且基本保持不变,只是对HomePage中的客户端组件进行了一些微小的更改:

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>
      
      <MorePosts>
    </div>
  );

}

然后,您将拥有如下所示的客户端组件:

'use client'

export const MorePosts = () => {

  // This is just some placeholder / pseudo-code for whatever custom logic
  // you need to fetch these:

  const { morePosts, loadMorePosts, areMorePostsLoading } = useMorePosts();

  return (
    <>
      <div className={ styles.morePostsList }>
        { morePosts.map((post) => (
          <PostCard post={ post } key={ post.slug } />
        )) }
      </div>

      <button
        onClick={ loadMorePosts }
        disabled={ areMorePostsLoading }>
        Load More
      </button>
    </>
  )
}

备注useMorePosts()代表一个定制钩子,它可能使用useEffectuseState加上fetchaxios或一些其他客户端请求库来加载页面/批处理中的附加帖子并存储它们,以及管理相关的状态(加载、错误、光标位置...).

Reactjs相关问答推荐

删除表2的收件箱未按预期工作

客户端组件中服务器组件的两难境地

Redux向后端发送请求时出现钩子问题

Reaction Axios多部分/表单-数据数组不工作

禁止直接访问Next.js中的页面,同时允许从应用程序内部访问

需要特定的数学函数来标准化动画持续时间

折叠并重新打开react 手风琴将重置内部状态

在 useSelector() 中使用 array.map() 如何导致组件在分派操作时重新渲染?

ReactJS 中的图像加载顺序

如何使用 redux 和 react-plotly.js

Cypress 组件测试不渲染react 组件(但它的内容)

如何在 ChartJS 中操作 Y 轴

为什么我在此代码段中看不到 useEffect for count = 1?

用 scss 覆盖 MUI

如何在 v6.4 中将 Auth0 提供程序与新的 createBrowsereRouter 一起使用?

在react 路由dom版本6中的组件内添加路由

axios post方法中的请求失败,状态码为500错误

在 Redux 中更新布尔状态时出错

RTK 查询 POST 方法不会改变数据

可以'读取未定义的属性(读取'路径')