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
相关产品推荐
相关产品推荐

