
本文将介绍如何使用自定义 Hook 在 React 组件之间传递数据,尤其是在使用 React Router 进行页面跳转时。通过自定义 Hook,我们可以更有效地管理和共享数据,避免在不同组件中重复获取数据,提高代码的可维护性和可重用性。本文将提供详细的代码示例,并解释如何将数据传递到使用 React Router 创建的详情页。
创建自定义 Hook
首先,创建一个名为 useCountry 的自定义 Hook,用于获取国家数据。这个 Hook 可以接收一个国家代码作为参数,并返回对应的数据。
// useCountry.js
import { useState, useEffect } from 'react';
function useCountry(countryCode) {
const [country, setCountry] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
async function fetchData() {
setLoading(true);
try {
const response = await fetch(`https://restcountries.com/v3.1/alpha/${countryCode}`);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
setCountry(data[0]); // Assuming the API returns an array
} catch (error) {
setError(error);
} finally {
setLoading(false);
}
}
if (countryCode) {
fetchData();
}
}, [countryCode]);
return { country, loading, error };
}
export default useCountry;代码解释:
- useState: 用于管理国家数据(country),加载状态(loading)和错误信息(error)。
- useEffect: 在组件挂载后或 countryCode 改变时,发起 API 请求。
- fetchData: 异步函数,用于获取国家数据。
- 错误处理: 包含 try...catch...finally 块,用于处理 API 请求可能出现的错误,并在请求完成后设置 loading 为 false。
- 返回值: Hook 返回一个包含 country,loading 和 error 属性的对象。
在 Details 组件中使用 Hook
在 Details.js 组件中,使用 useCountry Hook 获取特定国家的数据。这里假设通过路由参数传递国家代码。
// Details.js
import React from 'react';
import { useParams } from 'react-router-dom';
import Navbar from './components/Navbar';
import useCountry from './useCountry';
function Details() {
const { countryCode } = useParams(); // Get countryCode from route params
const { country, loading, error } = useCountry(countryCode);
if (loading) {
return <p>Loading country details...</p>;
}
if (error) {
return <p>Error: {error.message}</p>;
}
if (!country) {
return <p>Country not found</p>;
}
return (
<>
<Navbar />
<h1>Details</h1>
<div>
<h2>{country.name.common}</h2>
<p>Population: {country.population}</p>
{/* Display other country details here */}
</div>
</>
);
}
export default Details;代码解释:
- useParams: 从 React Router 获取路由参数,这里假设路由参数名为 countryCode。
- useCountry: 调用自定义 Hook,传入 countryCode,获取国家数据。
- 条件渲染: 根据 loading,error 和 country 的值,渲染不同的内容。
修改路由配置
确保路由配置正确,允许传递国家代码作为参数。
// main.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import './index.css';
import { createBrowserRouter, RouterProvider } from 'react-router-dom';
import Details from './Details';
const router = createBrowserRouter([
{
path: '/',
element: <App />,
},
{
path: '/details/:countryCode', // Add countryCode as a parameter
element: <Details />,
},
]);
ReactDOM.createRoot(document.getElementById('root')).render(
<React.StrictMode>
<RouterProvider router={router} />
</React.StrictMode>
);代码解释:
- /details/:countryCode: 定义路由,允许通过 :countryCode 传递国家代码作为参数。
修改 Country 组件
修改 Country.js 组件,使其传递正确的国家代码到 Details 页面。
// Country.js
import React from 'react';
import { Link } from 'react-router-dom';
function Country(props) {
const { data, img, cap, reg, alt, name, pop } = props;
const countryCode = data.cca2; // Assuming cca2 is the country code
return (
<Link to={`/details/${countryCode}`}>
<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;代码解释:
- countryCode: 从 data 属性中获取国家代码。这里假设 API 返回的数据中,cca2 字段是国家代码。
- Link: 使用 Link 组件,将 countryCode 作为路由参数传递到 Details 页面。
注意事项
- API 响应: 确保 API 响应的数据结构与代码中的假设一致。
- 错误处理: 在自定义 Hook 和组件中,添加适当的错误处理逻辑,以提高应用的健壮性。
- 性能优化: 如果需要频繁获取数据,可以考虑使用缓存机制,避免重复请求。
总结
通过创建自定义 Hook useCountry,可以有效地在 React 组件之间共享和管理数据。这种方法避免了在不同组件中重复获取数据,提高了代码的可维护性和可重用性。同时,结合 React Router 的路由参数,可以方便地将数据传递到详情页,实现更灵活的数据传递方式。










