React组件向页面传递数据失败问题咨询
问题:React Router通过Link state传值到Details页面变为null
在React项目中,将API获取的数据作为props传入Country组件,使用react-router创建Details页面后,尝试通过Link组件的state传递数据——Country组件内数据正常,但Details页面用useLocation接收时state变为null。
相关代码
Country.js(传值组件)
import React from 'react' import { Link } from 'react-router-dom' function Country(props) { const {data,img, cap, reg, alt, name, pop} = props return ( <Link to={{ pathname: '/details', state: { data } }}> <div className='w-72 h-80 shadow bg-white rounded-sm mx-auto cursor-pointer'> <img className='w-full h-1/2 rounded-sm' src={img} alt={alt} /> <div className='pt-3 pl-4'> <h3 className='font-extrabold pb-2 pt-1 text-darkBlue'>{name}</h3> <p className='text-sm text-darkBlue font-bold'>population: <span className='text-lightDarkGray font-normal' >{pop}</span></p> <p className='text-sm text-darkBlue font-bold'>region: <span className='text-lightDarkGray font-normal'>{reg}</span></p> <p className='text-sm text-darkBlue font-bold'>capital: <span className='text-lightDarkGray font-normal'>{cap}</span></p> </div> </div> </Link> ) } export default Country
Details.js(接收页面)
import React from 'react' import Navbar from './components/Navbar' import { useLocation } from 'react-router-dom' function Details() { const location = useLocation(); const { data } = location.state; return ( <> <Navbar/> <h1>Details</h1> {data ? ( <div> <h2>{data.name}</h2> <p>Population: {data.population}</p> </div> ) : ( <p>Country not found</p> )} </> ) } export default Details
main.js(路由配置)
import React from 'react' import ReactDOM from 'react-dom/client' import App from './App' import './index.css' import {createBrowserRouter,RouterProvider,Route} from 'react-router-dom' import Details from './Details' const router = createBrowserRouter([ { path: "/", element: <App/>, }, { path:"/details", element:<Details/> } ]); ReactDOM.createRoot(document.getElementById("root")).render( <React.StrictMode> <RouterProvider router={router} /> </React.StrictMode> )
App.js(数据获取)
import React from 'react' import { useState, useEffect } from 'react' import Navbar from './components/Navbar.jsx' import Search from './components/Search.jsx' import Country from './components/Country.jsx' function App() { const [data, setData] = useState([]); const [loadMore, setLoadMore] = useState(20) const [isDataMax, setIsDataMax] = useState(false) useEffect(() => { async function fetchData() { const response = await fetch('https://restcountries.com/v3.1/all'); const json = await response.json(); setData(json); } fetchData(); }, []); let onePageData = data.slice(0, loadMore) const load = ()=> { setLoadMore(loadMore + 20) if(loadMore == 240) { setIsDataMax(true) } } return ( <> <main className="main bg-veryLightGray w-full h-full mx-auto"> <Navbar/> <Search/> <article className='grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 items-center justify-stretch lg:w-128 gap-6 mx-auto'> {onePageData? onePageData.map((country,index) => <Country data={country} alt={onePageData[index].flags.alt} reg={country.continents} name={country.name.common} pop={country.population} cap={country.capital} img={onePageData[index].flags.png}/>): <p className='mx-auto text-10 font-bold'>Loading countries...</p> } </article> { !isDataMax && <button className='block mx-auto bg-darkBlue text-white px-4 py-2 font-bold rounded-lg mb-5 ' onClick={load}>Load More</button>} </main> </> ) } export default App
原因分析
- 数据序列化问题:API返回的country对象可能包含不可序列化的属性(如函数、Symbol、循环引用),React Router无法正确传递这类数据,导致state变为null。
- state的局限性:Link传递的state存储在内存中,若用户直接刷新Details页面,state会直接丢失;即使正常跳转,复杂对象也可能因序列化失败无法传递。
- 空值未处理:Details组件中直接解构
location.state,若state为null会引发报错,同时无法区分“无数据”和“数据未传递”的情况。
解决方案
方案一:序列化后传递数据
将复杂对象转换为可序列化的纯JSON对象,避免React Router传递时丢失数据:
修改Country组件的Link部分:
<Link to={{ pathname: '/details', state: { data: JSON.parse(JSON.stringify(data)) } }}>
同时在Details组件中添加空值保护:
const location = useLocation(); const data = location.state?.data; // 使用可选链避免state为null时报错
方案二:通过URL参数传递标识(推荐)
这种方式更可靠,不受页面刷新影响,同时符合RESTful设计:
- 修改Country组件的Link:传递国家唯一标识(如
cca3代码)作为URL参数
<Link to={`/details/${data.cca3}`}>
- 更新路由配置:在main.js中添加动态参数
const router = createBrowserRouter([ { path: "/", element: <App/>, }, { path:"/details/:countryCode", // 新增动态参数 element:<Details/> } ]);
- 修改Details页面:通过
useParams获取参数,重新请求对应国家的数据
import React, { useState, useEffect } from 'react' import Navbar from './components/Navbar' import { useParams } from 'react-router-dom' function Details() { const { countryCode } = useParams(); const [data, setData] = useState(null); const [loading, setLoading] = useState(true); useEffect(() => { async function fetchCountry() { try { const response = await fetch(`https://restcountries.com/v3.1/alpha/${countryCode}`); const json = await response.json(); setData(json[0]); } catch (error) { console.error('获取国家数据失败:', error); } finally { setLoading(false); } } fetchCountry(); }, [countryCode]); if (loading) return <p>加载中...</p>; if (!data) return <p>未找到该国家</p>; return ( <> <Navbar/> <h1>国家详情</h1> <div> <h2>{data.name.common}</h2> <p>人口: {data.population}</p> </div> </> ) } export default Details
方案三:确认React Router版本与写法
确保使用React Router v6(当前代码已使用createBrowserRouter,符合v6规范),同时在Details组件中严格处理空值:
const location = useLocation(); const data = location?.state?.data;
内容的提问来源于stack exchange,提问作者Ma Nar
相关产品推荐
相关产品推荐

