NextJS 中的 Apollo 分页

Posted

技术标签:

【中文标题】NextJS 中的 Apollo 分页【英文标题】:Pagination in NextJS with Apollo 【发布时间】:2021-11-10 03:44:39 【问题描述】:

我在 Nextjs 中实现了分页。 但我认为这不是一个好方法。 我用 JS 切片方法实现了分页..

这样实现分页是不是很糟糕?

我正在使用apollo client + apollo-server + mongodb(to save blog posts)+ graphql 堆栈

我知道其他人没有这样实现分页..

让我知道这样实现是可以的,如果不是这样,请告诉我实现分页的正确方法。

/components/pagination.tsx

import React from 'react';



interface PaginationProps 
    postsPerPage: number
    totalPosts: number
    paginate: (n: number) => void


const Pagination : React.FC<any> = ( postsPerPage, totalPosts, paginate  : PaginationProps) => 
    const pageNumbers : number[] = [];
    for (let i = 1; i <= Math.ceil(totalPosts/postsPerPage); i++) 
        pageNumbers.push(i);
    

    return (
        <div>
            <nav>
                <ul className="bg-purple-400 float-left mt-4 mb-4 text-center rounded-md text-white p-px">
                    pageNumbers.map(number => (
                        <li key=number className="inline-block text-base font-semibold rounded-md p-1 w-6 hover:bg-purple-500">
                            <span onClick=() => paginate(number) className="text-white">
                                number
                            </span>
                        </li>
                    ))
                </ul>
            </nav>
        </div>
    )



export default Pagination

/pages/index.tsx

import type  NextPage  from 'next'
import client from "../apollo-client";
import Link from 'next/link'
import Head from "next/head";
import GET_ALL_POSTS from "../lib/query";
import useState from "react";
import Pagination from "../components/pagination";


export async function getStaticProps() 
    const  data  = await client.query(
        query: GET_ALL_POSTS

    )
    return 
        props : 
            posts: data.posts
        ,
        revalidate: 10
    


const Home: NextPage = (posts : any) => 
    // Pagination
    const [currentPage, setCurrentPage] = useState(1);
    const [postsPerPage] = useState(10)
    const lastIndex = currentPage * postsPerPage;
    const firstIndex = lastIndex - postsPerPage;
    
    const currentPosts = (tmp : object[]) => 
        let currentPosts : object[] = [];
        currentPosts = tmp.slice(firstIndex, lastIndex);
        return currentPosts;
    

    return (
      <div>
          <Head>
              <title>...</title>
             
          </Head>
          <h1 className="text-gray-550 dark:text-white">전체 글(posts.length)</h1>

              <div className="flex items-center flex-col justify-center list-none">
                  currentPosts(posts).map((post : any, index : any) => (
                      <Link href=`/posts/$post._id` key=index>
                          <a className="group container mt-5 p-4 border-b-2">
                              <h3 className="text-black text-xl dark:text-white mt-4 group-hover:text-purple-500">post.title</h3>
                              <p className="text-black dark:text-white mb-4">renderDate(post.createdAt)</p>
                              renderTags(post.tags)
                          </a>
                      </Link>
                  ))
                  <Pagination postsPerPage=postsPerPage totalPosts=posts.length paginate=setCurrentPage/>
              </div>
      </div>


  )


export default Home

【问题讨论】:

【参考方案1】:

基本上,现在您正在预先获取所有帖子并动态计算它们所需的页面数量。根据帖子的数量,这可能是用户可能不需要的大量数据。

最好在用户需要时以增量方式获取数据。 Apollo 有一个 Pagination api 可以帮助您。来自文档:

服务器可以为特定列表字段使用许多不同的分页策略:基于偏移量、基于光标、基于页码、向前、向后等。每个策略都需要一组略有不同的参数。因为这些策略在不同的情况下都有用,所以 Apollo 和 GraphQL 规范都没有规定规范的分页策略。

我能给您的最佳建议是通读文档并找到您认为最适合您的情况的一种方法。您将大量使用的是fetchMorefunction,它允许您在用户与您的网站交互时获取更多帖子。这具有积极的副作用,您可能不需要每 10 秒调用一次revalidate。您可以将查询移至 Pagination 组件并在那里获取您希望在一页上显示的帖子数量。

【讨论】:

我实现了这个。但它需要加载..是否可以通过分页预取数据? (获取更多) 是的,您可以通过getStaticProps 预取前几篇文章。所以基本上你以前做的,但只获取一些帖子,而不是全部。 所以使用getStaticProps 预取就像限制:10? (mongodb 或 graphql)和fetchMore 其余的? 我想最好将前 10 个帖子作为一个名为 initialProps 的变量传递,然后在客户端开始页面 2 上开始获取。原因是我认为你不能传递 fetchMore轻松通过getStaticProps(我猜它会被序列化)。我认为这种方式更容易。

以上是关于NextJS 中的 Apollo 分页的主要内容,如果未能解决你的问题,请参考以下文章

Apollo 中 NextJs s-s-r 和 cookie 的问题

NextJS + Apollo:如何在 getServerSideProps 内的 apolloClient.query 上获取多个查询?

作为道具传递与提取缓存 Apollo 客户端 Nextjs

NextJS/Typescript/Apollo 错误;类型上不存在属性

如何从 NextJS 服务器为 Apollo 客户端补充水分

使用 NextJs 将 JWT 令牌传递到 Apollo 上下文