You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Next.js使用getServerSideProps实现表格分页API动态传参

实现方案

首先明确核心问题:你当前把接口请求逻辑全写在getServerSideProps里,这个函数只会在页面首次服务端渲染、服务端路由跳转时触发,客户端点击按钮不会重新执行它,所以写死的page=1不会动态变化。


关于是否需要useEffect的说明

不需要专门写useEffect在客户端发请求。如果硬要把分页请求挪到客户端做,确实可以用useEffect监听页码状态变化重新拉数据,但这种方案会丢失SSR首屏直出的优势,白屏时间更长,而且你已经在getServerSideProps里写好的数据过滤、字段格式化逻辑要在客户端重复写一遍,冗余度高,不推荐。

最合适的方案是把页码同步到路由query参数中,让getServerSideProps跟着路由参数的变化自动拉取对应页的数据,全程复用已有的服务端数据处理逻辑,不需要额外写客户端请求代码。


具体修改步骤

1. 改造getServerSideProps支持动态页码

把原来写死的page=1改成从路由参数里读取动态值,同时加参数合法性校验,避免非法页码参数导致报错:

export async function getServerSideProps(context) {
    const { params, res, query } = context
    const { tabla } = params
    // 从query取页码,默认值为1,转成数字类型
    const currentPage = Number(query.page) || 1
    const pageSize = 25
    // 替换固定page参数为动态值
    const apiResponse = await fetch(`${process.env.NEXT_PUBLIC_API_URL}admin/users/signup-status?page=${currentPage}&page_size=${pageSize}`)
    if (apiResponse.ok) {
        let responseData = await apiResponse.json()

        const mapped = responseData.results.map(user => {
            return {
                ...user,
                wait_time: parseInt(user.wait_time.split(' ')[0]) || 0
            }
        })
        let data = mapped

        // 原有数据过滤、字段处理逻辑完全保留
        if (tabla === 'cartera') {
            data = mapped.map(user => {
                const dataUser = { ...user }
                delete dataUser.wait_time
                return dataUser
            })
        } else {
            data = mapped.filter(user => {
                if (tabla === 'primera') {
                    return user.status === 'revision'
                }
                if (tabla === 'segunda') {
                    return user.status === 'segunda'
                }
                if (tabla === 'seguimiento') {
                    return user.status === 'seguimiento' || user.status === 'caducado'
                }
            })
            if (tabla === 'primera') {
                data = data.map(user => {
                    const dataUser = { ...user }
                    delete dataUser.comments
                    return dataUser
                })
            }
        }

        // 计算总页数,做页码合法性校验
        const totalPages = Math.ceil(responseData.count / pageSize)
        if (currentPage < 1 || currentPage > totalPages) {
            res.writeHead(302, { location: `/${tabla}?page=1` }).end()
            return { props: {} }
        }
        const pages = Array.from({ length: totalPages }, (_, i) => i + 1)

        // 把当前页码、总页数列表传给组件
        return {
            props: {
                data,
                pages,
                currentPage
            }
        }
    }

    if (res) {
        res.writeHead(301, { location: '/404' }).end()
    }
}

2. 改造前端组件,给分页按钮加跳转逻辑

删掉原来没用的本地pageIndex状态,直接用服务端传回来的当前页码,点击按钮时通过路由跳转修改page参数即可,路由变化后会自动触发getServerSideProps拉取新页数据:

const UnderWriting = (props) => {
    // 从props解构服务端传回的分页数据
    const { data, currentPage, pages } = props
    const [dataToShow, setDataToShow] = useState(data)
    const [title, setTitle] = useState('')

    const router = useRouter()
    const { tabla } = router.query

    // 分页跳转方法
    const handlePageChange = (targetPage) => {
        router.push({
            pathname: router.pathname,
            query: {
                ...router.query,
                page: targetPage
            }
        })
    }

    useEffect(() => {
        switch (tabla) {
            case 'primera': {
                setTitle('Primera revision de UW')
                break
            }
            case 'segunda': {
                setTitle('Segunda revision de UW')
                break
            }
            case 'seguimiento': {
                setTitle('En Seguimiento UW')
                break
            }
            case 'cartera': {
                setTitle('Cartera de UW')
                break
            }
        }
        setDataToShow(data)
    }, [tabla, data])

    const totalPages = pages.length
    return (
        <Box>
            <Box> 
                <Box color='#96A0AA' border='1px solid #DFE6EE' boxShadow='lg' overflow='hidden' rounded='lg'>
                    <TablesData data={dataToShow}  />
                </Box>
                <Center>
                    <HStack mt={5} mb={5} >
                        <Button 
                            onClick={() => handlePageChange(currentPage - 1)}
                            isDisabled={currentPage === 1}
                        >
                            Anterior
                        </Button>
                        <Button 
                            onClick={() => handlePageChange(currentPage + 1)}
                            isDisabled={currentPage === totalPages}
                        >
                            Siguiente
                        </Button>
                    </HStack>
                </Center>
            </Box>
        </Box>
    );
}

方案优势

  • 完全适配Next.js Pages Router的SSR设计,首屏直出速度快,不损失SEO能力
  • 页码存在URL参数中,用户刷新页面、分享链接、点击浏览器前进后退都能准确定位到对应页码,不会重置到第一页
  • 所有数据处理逻辑都在服务端完成,不需要在客户端重复写接口请求、数据格式化代码,维护成本低
  • 分页按钮自带禁用状态逻辑,边界情况处理完善,不会出现请求小于1或者超出总页数的无效接口

内容的提问来源于stack exchange,提问作者Federico Lombardozzi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.03 01:15:39