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

Next.js中如何在getServerSideProps实现筛选分页传参

实现方案

getServerSideProps 是服务端执行的函数,无法直接读取客户端组件内的状态,所有动态筛选、分页、排序参数都要从当前页面的URL查询参数中获取。当交互触发参数更新时,通过Next.js路由方法修改URL,框架会自动重新执行getServerSideProps拉取新数据,效果和客户端useEffect监听依赖触发请求完全一致,且天然支持SEO。


第一步:改造getServerSideProps接收动态参数

getServerSideProps 默认会接收上下文对象context,其中的query字段就是当前URL携带的所有查询参数,直接把参数拼到接口请求中即可,不要硬编码固定的分页、排序值:

export const getServerSideProps = async (context) => {
  // 从URL参数中解构分页、排序、筛选项,配置默认值兜底
  const {
    page = 1,
    limit = 20,
    sortBy = 'price',
    sortAs = 'asc'
    // 后续新增筛选项(如分类、价格区间)直接在此处解构即可
  } = context.query;

  const res = await fetch(`http://localhost:4000/api/products?page=${page}&limit=${limit}&sortBy=${sortBy}&sortAs=${sortAs}`);
  const data = await res.json();

  // 把当前查询参数一并传给组件,用于控件状态回显
  return {
    props: {
      productsData: data,
      currentQuery: {
        page: Number(page),
        limit: Number(limit),
        sortBy,
        sortAs
      }
    }
  }
}

第二步:添加交互逻辑,更新URL触发数据刷新

不需要在客户端额外用useEffect拉数据,直接用Next.js内置的路由方法,用户操作分页、筛选、排序控件时,把新参数拼接到URL上跳转即可,框架会自动重新执行服务端数据拉取逻辑:

import { useRouter } from 'next/router';
// 原有依赖(Row、Col、Card、Link、Rating等)保持不变

function Home({ productsData, currentQuery }) {
  const router = useRouter();
  // 简化原有冗余的商品数据处理逻辑,空数组兜底
  const products = productsData?.data?.products || [];

  // 通用查询参数更新方法
  const updateQuery = (newParams) => {
    router.push({
      pathname: router.pathname,
      query: { ...router.query, ...newParams }
    });
  };

  return (
    <>
      <h1>Latest Products</h1>
      {/* 排序控件示例 */}
      <div className="sort-bar mb-3">
        <select
          value={currentQuery.sortBy}
          onChange={(e) => updateQuery({ sortBy: e.target.value, page: 1 })}
        >
          <option value="price">按价格排序</option>
          <option value="createdAt">按上架时间排序</option>
          <option value="rating">按评分排序</option>
        </select>
        <select
          value={currentQuery.sortAs}
          onChange={(e) => updateQuery({ sortAs: e.target.value, page: 1 })}
          className="ml-2"
        >
          <option value="asc">升序</option>
          <option value="desc">降序</option>
        </select>
      </div>

      <Row>
        {products.map((product) => (
          // 原有商品卡片逻辑完全不需要修改
          <Col key={product.id} sm={12} md={6} lg={4} xl={3}>
            <Card className="my-3 p-3 rounded">
              <Link href={`/product/${product.id}`}>
                <Card.Img src={product.image} variant="top" />
              </Link>
              <Card.Body>
                <Link href={`/product/${product.id}`}>
                  <Card.Title as="div">
                    <strong>{product.name}</strong>
                  </Card.Title>
                </Link>
                <Card.Text as="div">
                  <Rating
                    value={product.rating}
                    text={`${product.numReviews} reviews`}
                  />
                </Card.Text>
                <Card.Text as="h3">${product.price}</Card.Text>
              </Card.Body>
            </Card>
          </Col>
        ))}
      </Row>

      {/* 分页控件示例 */}
      <div className="pagination-wrap mt-4">
        <button
          disabled={currentQuery.page <= 1}
          onClick={() => updateQuery({ page: currentQuery.page - 1 })}
        >
          上一页
        </button>
        <span className="mx-3">第 {currentQuery.page} 页</span>
        <button
          // 总页数从接口返回的字段中取,此处为示例逻辑
          disabled={currentQuery.page >= productsData?.data?.totalPage}
          onClick={() => updateQuery({ page: currentQuery.page + 1 })}
        >
          下一页
        </button>
      </div>

      {/* 可选:加载状态提示 */}
      {router.isLoading && <div className="loading-tip">数据加载中...</div>}
    </>
  );
}

export default Home

注意事项

  • 从URL query中取出的参数默认是字符串类型,涉及数字判断(如页码、每页条数)记得提前转成数值类型,避免逻辑判断出错
  • 后续新增任意筛选项都遵循同样逻辑:控件收集用户选择的参数→更新URL query→getServerSideProps取参数传给后端接口即可
  • 生产环境不要硬编码localhost:4000的接口地址,建议用环境变量统一配置接口域名,避免部署后请求失败
  • 如果需要更平滑的切换体验,可以在router.isLoading为true时展示骨架屏,替代生硬的加载提示

内容的提问来源于stack exchange,提问作者Sanjeet Kunwar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 21:54:32