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

React与Next.js中Router传参仅显示单条数据问题

问题:搜索后跳转页面仅显示单条数据的原因及修复方案

核心问题分析

你代码里的关键错误出在Page1的渲染逻辑中:

  • 你在组件顶层直接用property.map()循环调用router.push,这会导致每次property状态更新时,循环执行跳转操作。由于router.push是异步操作,多次调用会覆盖之前的跳转请求,最终只有最后一次跳转的参数被传递到Page2,所以页面只显示最后一条数据。
  • 同时,在React组件的渲染阶段执行跳转这类副作用操作,本身就违反了React的渲染规则——渲染阶段应该只负责生成UI,不能包含状态修改、路由跳转这类副作用。

修复方案

根据你的需求,分两种场景给出修复代码:

场景1:需要跳转到Page2展示所有搜索结果

修改Page1,将所有结果的ID和名称通过路由参数传递,同时移除渲染阶段的副作用:

import React, { useState } from "react"
import { useRouter } from "next/router"

function PropertyList() {
  const [searchInput, setSearchInput] = useState("");
  const [property, setProperty] = useState([]);
  const router = useRouter();

  const fetchPropertiesInfo = async () => {
    const api_token = process.env.NEXT_PUBLIC_API_TOKEN
    const response = await fetch(`dummy/api/filter?term=${searchInput}`, {
      method: 'GET',
      headers: {
        'Authorization': 'Bearer ' + api_token,
        'Content-Type': 'application/json',
        'Accept': "application/vnd.v1+json"
      }
    })
    const data = await response.json()
    setProperty(data.properties)
  }

  // 点击按钮跳转结果页,传递所有结果的参数
  const goToAllResults = () => {
    const ids = property.map(p => p.id).join(',');
    const names = property.map(p => p.name).join(',');
    router.push({
      pathname: "/PageTwo",
      query: { ids, names }
    })
  }

  return (
    <>
      <div className="pt-24">
        <div className="flex justify-center items-center">
          <input onChange={(e) => setSearchInput(e.target.value)} type="text" className="p-2 border border-primaryOrange" />
          <button onClick={fetchPropertiesInfo} className='bg-primaryOrange text-white rounded-sm p-2'>Search</button>
          {/* 搜索有结果时显示跳转按钮 */}
          {property.length > 0 && (
            <button onClick={goToAllResults} className='ml-2 bg-primaryOrange text-white rounded-sm p-2'>查看全部结果</button>
          )}
        </div>
        <h1 className="text-center mt-4">搜索结果列表</h1>
      </div>
    </>
  )
}

export default PropertyList

修改Page2,解析传递的批量参数并渲染所有结果:

import { useRouter } from 'next/router';

function DisplayResults() {
  const router = useRouter();
  const { ids, names } = router.query;

  // 处理批量结果
  if (ids && names) {
    const idList = ids.split(',');
    const nameList = names.split(',');
    return (
      <div className='py-20'>
        <h1 className="text-center text-xl mb-6">全部搜索结果</h1>
        <div className="flex flex-col items-center">
          {idList.map((id, index) => (
            <div key={id} className='py-3 border-b w-1/2 text-center'>
              <p className="text-sm">ID: {id}</p>
              <h3 className="mt-1">{nameList[index]}</h3>
            </div>
          ))}
        </div>
      </div>
    )
  }

  return <div className='py-40 flex justify-center'>加载中...</div>
}

export default DisplayResults

场景2:需要点击单条结果跳转到详情页

如果你的需求是先在Page1展示搜索结果列表,点击单条后跳转到Page2查看详情,修改Page1如下:

// ... 保留其他代码不变
return (
  <>
    <div className="pt-24">
      <div className="flex justify-center items-center">
        <input onChange={(e) => setSearchInput(e.target.value)} type="text" className="p-2 border border-primaryOrange" />
        <button onClick={fetchPropertiesInfo} className='bg-primaryOrange text-white rounded-sm p-2'>Search</button>
      </div>
      <h1 className="text-center mt-4">搜索结果列表</h1>
      {/* 渲染结果列表,点击跳转单条详情 */}
      <div className="mt-6 max-w-2xl mx-auto">
        {property.map((p) => (
          <div 
            key={p.id} 
            onClick={() => router.push({
              pathname: "/PageTwo",
              query: { id: p.id, name: p.name }
            })} 
            className="p-3 border rounded mb-2 cursor-pointer hover:bg-gray-50"
          >
            <h3>{p.name}</h3>
            <p className="text-sm text-gray-600">ID: {p.id}</p>
          </div>
        ))}
      </div>
    </div>
  </>
)

对应的Page2可以保持原有逻辑,只渲染单条数据即可。

关键注意事项

  • 永远不要在React组件的渲染阶段执行路由跳转、数据请求这类副作用操作,应该把这些逻辑放在事件处理函数(比如点击事件)或者useEffect钩子中。
  • 如果需要传递多条数据,建议通过批量参数拼接(如逗号分隔)或者序列化后的JSON字符串传递,注意路由参数的长度限制;如果数据量较大,也可以考虑用Next.js的路由state传递(router.push的第二个参数可以携带state)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 13:45:47