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

Next.js中如何将React状态传递给GraphQL变量实现数组数据过滤

核心问题说明

getStaticProps 是 Next.js 服务端侧执行的生命周期,仅在构建阶段、后台增量重生成时运行,完全无法访问客户端运行时的 React 状态,所以直接把组件内的 filter 传入 getStaticProps 的查询变量是不可能实现的,以下是3种可行实现方案:


方案1:全量预取 + 客户端过滤(最简单,适合数据量≤1000条的场景)
  • 实现逻辑:getStaticProps 不传入name过滤条件,先拉取全量列表数据,组件内用状态filter直接对预取到的全量数据做过滤
  • 代码示例:
// getStaticProps 去掉name变量,查询全量数据
export async function getStaticProps() {
 const { data, errors } = await client.query({
    query: GET_LISTINGS,
    variables: {
        uri: '/listing/',
        name: '' // 传空或者直接去掉这个变量,查全量
    }
  })
  return {
    props: {
        allData: data || [],
    },
    revalidate: 1
  }
}

const Listings = ({ allData }) => {
  const [filter, setFilter] = useState({
      city: '',
      area: '',
      type: '',
  })
  // 新增过滤逻辑
  const filteredData = allData?.listingCategoriesL?.nodes?.filter(category => {
    if (!filter.city) return true
    return category.name === filter.city
  }) || []

  const handleSelectedFilter = e => {
    setFilter({ ...filter, [e.target.name]: e.target.value })
  }

  // 渲染filteredData即可
  return <div>{/* 渲染过滤后的列表 */}</div>
}
export default Listings
  • 优缺点:实现成本最低,过滤无网络请求延迟,仅适合数据量不大的场景

方案2:客户端发起GraphQL查询(最灵活,适合数据量大、过滤条件多的场景)
  • 实现逻辑:把GraphQL查询从getStaticProps移到组件内部,使用Apollo Client的useQuery钩子,或者SWR/React Query等请求库,监听filter变化自动发起带过滤条件的查询
  • 代码示例:
// 不需要在getStaticProps里查数据了,直接删掉getStaticProps,或者保留查首屏默认数据
const Listings = () => {
  const [filter, setFilter] = useState({
      city: '',
      area: '',
      type: '',
  })
  // 用useQuery触发查询,自动监听filter.city变化重新请求
  const { data, loading } = useQuery(GET_LISTINGS, {
    variables: {
      uri: '/listing/',
      name: filter.city
    }
  })

  const handleSelectedFilter = e => {
    setFilter({ ...filter, [e.target.name]: e.target.value })
  }

  if (loading) return <div>加载中...</div>
  return <div>{/* 渲染data里的列表 */}</div>
}
export default Listings
  • 优缺点:过滤逻辑灵活,支持任意复杂的多条件组合,过滤时会发起网络请求,需要处理加载状态

方案3:URL参数同步过滤状态 + 服务端查询(适合需要SEO、页面分享的场景)
  • 实现逻辑:把用户选中的过滤条件同步到URL的查询参数中,比如选择city=北京时跳转到/listing?city=北京,在getServerSideProps中读取URL参数的值,传入GraphQL查询变量返回过滤后的数据
  • 代码示例:
export async function getServerSideProps(context) {
  // 从URL查询参数中获取city
  const { city = '' } = context.query
  const { data, errors } = await client.query({
    query: GET_LISTINGS,
    variables: {
        uri: '/listing/',
        name: city
    }
  })
  return {
    props: {
        data: data || [],
        defaultCity: city
    }
  }
}

const Listings = ({ data, defaultCity }) => {
  const [filter, setFilter] = useState({
      city: defaultCity || '',
      area: '',
      type: '',
  })

  const handleSelectedFilter = e => {
    const newCity = e.target.value
    setFilter({ ...filter, [e.target.name]: newCity })
    // 同步到URL参数,触发服务端重新查询
    window.history.pushState({}, '', `/listing?city=${encodeURIComponent(newCity)}`)
  }

  return <div>{/* 渲染data里的列表 */}</div>
}
export default Listings
  • 优缺点:过滤后的页面可以直接分享,支持搜索引擎收录,每次过滤会触发页面级的服务端请求,延迟相对高一点

内容的提问来源于stack exchange,提问作者London Creative

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 02:15:10