使用 Apollo 在 NextJS 中分页
Pagination in NextJS with Apollo
我在 Nextjs 中实现了分页。
但我认为这不是好方法。
我用 JS slice 方法实现了分页..
这样实现分页不好吗?
我正在使用 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
基本上,现在您可以预先获取所有帖子并动态计算它们所需的页面数量。根据帖子的数量,这可能是用户可能不需要的大量数据。
最好是在用户需要时增量获取数据。 Apollo 有一个 Pagination api 可以帮助你。来自文档:
There are many different pagination strategies a server can use for a particular list field: offset-based, cursor-based, page-number-based, forwards, backwards, and so on. Each strategy requires a slightly different set of arguments. Because these strategies can each be useful in different situations, neither Apollo nor the GraphQL specification prescribes a canonical pagination strategy.
我能给你的最好建议是通读文档并找到你认为最适合你情况的方法。您将大量使用的是 fetchMore
function,它允许您在用户与您的站点交互时获取更多帖子。这具有积极的副作用,您可能不需要每 10 秒调用一次 revalidate
。您可以将查询移动到 Pagination
组件并在那里获取您想要在一页上显示的帖子数量。
我在 Nextjs 中实现了分页。 但我认为这不是好方法。 我用 JS slice 方法实现了分页..
这样实现分页不好吗?
我正在使用 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
基本上,现在您可以预先获取所有帖子并动态计算它们所需的页面数量。根据帖子的数量,这可能是用户可能不需要的大量数据。
最好是在用户需要时增量获取数据。 Apollo 有一个 Pagination api 可以帮助你。来自文档:
There are many different pagination strategies a server can use for a particular list field: offset-based, cursor-based, page-number-based, forwards, backwards, and so on. Each strategy requires a slightly different set of arguments. Because these strategies can each be useful in different situations, neither Apollo nor the GraphQL specification prescribes a canonical pagination strategy.
我能给你的最好建议是通读文档并找到你认为最适合你情况的方法。您将大量使用的是 fetchMore
function,它允许您在用户与您的站点交互时获取更多帖子。这具有积极的副作用,您可能不需要每 10 秒调用一次 revalidate
。您可以将查询移动到 Pagination
组件并在那里获取您想要在一页上显示的帖子数量。