React项目中基于public目录data.json实现动态路由的问题
解决React中从public目录data.json加载对应ID房产数据的问题
你现在的核心问题是:虽然通过useParams拿到了路由里的id,但没从加载的完整数据数组里筛选出对应项;而且之前尝试在fetch的URL后拼接id是行不通的——因为你的data.json是存储所有房产的数组文件,并非按ID拆分的单个文件。
具体修改步骤
- 调整状态定义:不需要存储整个房产数组,直接存单个匹配的房产对象,初始值设为
null便于判断加载状态。 - 筛选匹配数据:在
fetch成功后,用Array.find()方法根据路由id筛选对应项,注意useParams返回的id是字符串,要转成数字和data.json里的数字ID匹配。 - 更新依赖项:把
id加入useEffect的依赖数组,确保路由ID变化时重新筛选数据。 - 处理渲染边界:渲染前先判断数据是否存在,避免出现
Cannot read properties of null的错误。
修改后的RentalPage.jsx完整代码
import { useEffect, useState } from "react"; import { useParams } from "react-router-dom"; const RentalPage = () => { const { id } = useParams(); // 存储单个匹配的房产数据,初始为null const [property, setProperty] = useState(null); const getData = () => { fetch("/data.json", { headers: { "Content-Type": "application/json", Accept: "application/json", }, }) .then(response => response.json()) .then(myJson => { // 将路由id转为数字,匹配对应房产 const matchedProperty = myJson.find(item => item.id === Number(id)); setProperty(matchedProperty); }); }; // 路由id变化时重新执行数据获取逻辑 useEffect(() => { getData(); }, [id]); return ( <> {property ? ( <h1>{property.name}</h1> ) : ( <p>加载中...</p> )} </> ); }; export default RentalPage;
可选优化方案(减少重复请求)
如果想避免每次进入详情页都重新请求整个data.json,可以在列表页跳转时直接把房产数据通过路由状态传过去:
- 修改Rentals.jsx中的Link:
<Link to={`/rentals/${property.id}`} state={{ property }}>BOOK NOW</Link>
- 修改RentalPage.jsx,优先使用路由状态的数据,没有再去请求:
import { useEffect, useState } from "react"; import { useParams, useLocation } from "react-router-dom"; const RentalPage = () => { const { id } = useParams(); const location = useLocation(); // 优先用路由状态传过来的数据,没有则初始为null const [property, setProperty] = useState(location.state?.property || null); const getData = () => { fetch("/data.json", { headers: { "Content-Type": "application/json", Accept: "application/json", }, }) .then(response => response.json()) .then(myJson => { const matchedProperty = myJson.find(item => item.id === Number(id)); setProperty(matchedProperty); }); }; // 只有当没有路由状态数据时才请求 useEffect(() => { if (!property) { getData(); } }, [id, property]); return ( <> {property ? ( <h1>{property.name}</h1> ) : ( <p>加载中...</p> )} </> ); }; export default RentalPage;
内容的提问来源于stack exchange,提问作者jonteal
相关产品推荐
相关产品推荐

