我正在制作一个类似论坛的网站,其中包含一个组件来显示不同的论坛,并使用分页按钮来使用 Next.js 显示下一页。
我当前的页面实现是,我将使用 getServerSideProps
查询数据以进行初始页面加载。之后,当用户单击下一页
按钮时显示论坛的下一页。
我想查询在 getServerSideProps
中调用的同一 API 以获取下一页数据。
我设法让按钮正常工作。但问题是 setPage
设置的 page
数量似乎与 UI 不同步。
这是代码:
import dayjs from 'dayjs'
import type { GetServerSidePropsResult } from 'next'
import Head from 'next/head'
import Link from 'next/link'
import { useState } from 'react'
import type { GetPostListRequestQueries } from '@/types/GetPostListRequestQueries'
import type { GetPostListResponseBody } from '@/types/GetPostListResponseBody'
export async function getServerSideProps (): Promise<GetServerSidePropsResult<{ announcements: GetPostListResponseBody }>> {
const queries: GetPostListRequestQueries = {
announcement: true,
category_based_announcement: false,
page: 1
}
try {
const url = new URL('http://127.0.0.1:5155/forum/posts')
const searchParams = new URLSearchParams(queries as Record<string, string>)
url.search = searchParams.toString()
const response = await fetch(url)
const announcements: GetPostListResponseBody = await response.json()
return {
props: {
announcements
}
}
} catch (e) {
const response: GetPostListResponseBody = {
posts: []
}
return {
props: {
announcements: response
}
}
}
}
function Forum ({ announcements }: { announcements: GetPostListResponseBody }): JSX.Element {
const [page, setPage] = useState(1)
const [pageAnnouncements, setPageAnnouncements] = useState(announcements)
const fetchAnnouncements = async (): Promise<void> => {
const queries: GetPostListRequestQueries = {
announcement: true,
category_based_announcement: false,
page
}
try {
const url = new URL('http://127.0.0.1:5155/forum/posts')
const searchParams = new URLSearchParams(queries as Record<string, string>)
url.search = searchParams.toString()
const response = await fetch(url)
const announcements: GetPostListResponseBody = await response.json()
setPageAnnouncements(announcements)
} catch (e) {
const response: GetPostListResponseBody = {
posts: []
}
setPageAnnouncements(response)
}
}
async function goToPreviousPage (): Promise<void> {
setPage(() => page - 1)
await fetchAnnouncements()
}
async function goToNextPage (): Promise<void> {
setPage(() => page + 1)
await fetchAnnouncements()
}
return (
<>
<Head>
<title>Forum • ger</title>
<meta name="description" content="reg spelled backwards" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
</Head>
<main className="container mx-auto">
<h1 className="text-4xl text-current font-bold">Forum {page}</h1>
<div className="flex flex-row justify-between">
<h3 className="text-2xl text-current">Global announcements</h3>
<div className="flex flex-row btn-group">
<button className="btn" onClick={goToPreviousPage}>Previous page</button>
<button className="btn" onClick={goToNextPage}>Next page</button>
</div>
</div>
<div className="overflow-x-auto">
<table className="table w-full">
<thead>
<tr>
<td>Topic</td>
<td>Replies</td>
<td>Views</td>
<td>Activity</td>
</tr>
</thead>
<tbody>
{
pageAnnouncements.posts.map(a => {
return (
<tr key={a.id}>
<td>
<Link className="font-bold link link-hover" href={{ pathname: '/forum/posts/[postId]', query: { postId: a.id } }}>{a.name}</Link>
<div className="flex flex-row">
<Link className="text-sm opacity-75 link link-hover" href={{ pathname: '/forum/users/[username]', query: { username: a.username } }}>
{a.username}
</Link>
<p className="text-sm opacity-75">
• {dayjs(a.created_timestamp).format('MMMM D, YYYY HH:mm')}
</p>
</div>
</td>
<td>10</td>
<td>{a.view_count}</td>
<td>1h</td>
</tr>
)
})
}
</tbody>
</table>
</div>
<h3 className="text-2xl text-current font-bold">Trending</h3>
<div className="overflow-x-auto">
<table className="table w-full">
<tbody>
<tr>
<td>Cy Ganderton</td>
<td>Quality Control Specialist</td>
<td>Blue</td>
</tr>
</tbody>
</table>
</div>
</main>
</>
)
}
export default Forum
从下面的gif中可以看到,“论坛”一词旁边的数字和查询时使用的数字始终为1。
我是 Nextjs 的新手,不理解这种行为。感谢您的帮助。
最佳答案
说明
调用setState
不立即更新相关state
。需要重新渲染。这怎么样setState
设计作品。作为doc说:
The
set
function only updates the state variable for the next render. If you read the state variable after calling the set function, you will still get the old value that was on the screen before your call.
在 goToPreviousPage
和goToNextPage
您正在调用setPage
并立即fetchAnnouncements
,所以它使用 page
的值来自之前的渲染。
解决方案
您可以做的就是通过 page
使其在很少的更改下工作。至fetchAnnouncements
作为参数,如下所示:
const fetchAnnouncements = async (page: number): Promise<void> => {
// ...
}
async function goToPreviousPage (): Promise<void> {
setPage(() => page - 1)
await fetchAnnouncements(page - 1)
}
async function goToNextPage (): Promise<void> {
setPage(() => page + 1)
await fetchAnnouncements(page + 1)
}
关于javascript - `setState` 未与UI同步,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/75507057/