Edison's Studio.

nextjs-pagination

Word count: 502Reading time: 2 min
2024/02/01
loading

环境

1
2
3
node: v20.11.0
npm: 10.2.4
next: 14.1.0

初始化应用

1
npx create-next-app

客户端渲染

  • 客户端渲染要求自身及子组件都是客户端渲染,即都需要上声明 'use client'
  • state 触发整个 DOM 重新渲染,所以使用必须是客户端渲染
  • 客户端重新渲染,页面内容也要更新,所以描述页面的 DOM 也被当作客户端渲染组件,也需要声明 'use client'; 所以该组件不能以 children 组件传入。

理解了客户端渲染的方式,就可以很容易的实现分页了。

实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// app/page.tsx

import { cache } from 'react'

import { PaginatedData, Pagination } from './pagination'

export const getData = cache(() => {
return {
data: [
{ id: 1, name: 'a' },
{ id: 2, name: 'b' },
{ id: 3, name: 'c' },
{ id: 4, name: 'd' },
{ id: 5, name: 'e' },
{ id: 6, name: 'f' },
]
}
})


export default function Page() {
const data = getData()

return (
<div>
<Pagination data={data.data} itemsPerPage={2}
paginationEle={PaginatedData}
/>
</div>
)

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
// app/pagination.tsx
// 由 GPT-4 自动生成

'use client'

import React, { useState } from 'react'

export function Pagination({ data, itemsPerPage, paginationEle }: {
data: any[]
itemsPerPage: number
paginationEle: (data: any[]) => JSX.Element
}) {
let [currentPage, setCurrentPage] = useState(0)

const maxPage = Math.ceil(data.length / itemsPerPage) - 1
const start = currentPage * itemsPerPage
const end = start + itemsPerPage

return (
<>
{paginationEle(data.slice(start, end))}
<div className="flex justify-between my-4 space-x-4">
<button
disabled={currentPage === 0}
onClick={() => setCurrentPage(currentPage - 1)}
className={`px-4 py-2 rounded shadow ${currentPage === 0 ? 'bg-gray-300' : 'bg-gray-500 hover:bg-gray-700'} text-white`}
>
Previous
</button>
<button
disabled={currentPage === maxPage}
onClick={() => setCurrentPage(currentPage + 1)}
className={`px-4 py-2 rounded shadow ${currentPage === maxPage ? 'bg-gray-300' : 'bg-gray-500 hover:bg-gray-700'} text-white`}
>
Next
</button>
</div>
</>
)
}

export function PaginatedData(data: any[]) {
return (
<div>
{data.map((item) => (
<div key={item.id}>{item.id}: {item.name}</div>
))}
</div>
)
}

CATALOG
  1. 1. 环境
  2. 2. 初始化应用
  3. 3. 客户端渲染
  4. 4. 实现