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

React组件向页面传递数据失败问题咨询

在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

原因分析

  1. 数据序列化问题:API返回的country对象可能包含不可序列化的属性(如函数、Symbol、循环引用),React Router无法正确传递这类数据,导致state变为null。
  2. state的局限性:Link传递的state存储在内存中,若用户直接刷新Details页面,state会直接丢失;即使正常跳转,复杂对象也可能因序列化失败无法传递。
  3. 空值未处理: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设计:

  1. 修改Country组件的Link:传递国家唯一标识(如cca3代码)作为URL参数
<Link to={`/details/${data.cca3}`}>
  1. 更新路由配置:在main.js中添加动态参数
const router = createBrowserRouter([
  {
    path: "/",
    element: <App/>,
  },
  {
    path:"/details/:countryCode", // 新增动态参数
    element:<Details/>
  }
]);
  1. 修改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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 01:37:17