如何调整cityData结构以实现Next.js路由城市名匹配过滤
问题说明
我正在制作模拟数据文件,其中cityData对象包含多个城市数据,但每个城市对应一个由4个对象组成的数组,导致在Next.js的城市UI文件里没法根据路由路径名匹配到对应城市数据。尝试用Object.keys时出现类型错误,希望调整cityData结构,让它能通过filter或者Object.keys实现城市名和路由路径名的匹配。
现有City UI文件代码
import { useRouter } from "next/router"; import { cityData } from "../api/dummydata"; export default function service() { const router = useRouter() const city = router.asPath.replace("/", "").replace("%20", " ") const data = cityData // 试过 const data = cityData.Object.keys(city) - 会提示类型错误:Object不存在 return () }
当前cityData结构
Object austin: (4) [{…}, {…}, {…}, {…}] dallas: (4) [{…}, {…}, {…}, {…}] el_paso: (4) [{…}, {…}, {…}, {…}] galveston: (4) [{…}, {…}, {…}, {…}] houston: (4) [{…}, {…}, {…}, {…}] san_antonio: (4) [{…}, {…}, {…}, {…}]
现有数据文件代码
export const cityData = { austin: [ {details:""}, {sights: []}, {more_details:""}, {image: ""} ], dallas: [ {details:""}, {sights: []}, {more_details:""}, {image:"../assets/dallas.jpg"} ], el_paso: [ {details:""}, {sights: []}, {more_details:""}, {image:"../assets/el-paso-texas.jpg"} ], galveston: [ {details:""}, {sights: []}, {more_details:""}, {image:"../assets/galveston-island.jpg"} ], houston: [ {details:""}, {sights: []}, {more_details:""}, {image:"../assets/houston.jpg"} ], san_antonio: [ {details:""}, {sights: []}, {more_details:""}, {image:"../assets/san_antonio.jpg"} ], }
解决方案
调整cityData结构(推荐)
把每个城市对应的拆分数组合并为单个对象,并新增citySlug字段对应路由里的标识(处理空格转下划线的情况),这样能直接用filter匹配。调整后的数据结构如下:
export const cityData = [ { citySlug: "austin", details: "", sights: [], more_details: "", image: "" }, { citySlug: "dallas", details: "", sights: [], more_details: "", image: "../assets/dallas.jpg" }, { citySlug: "el_paso", details: "", sights: [], more_details: "", image: "../assets/el-paso-texas.jpg" }, { citySlug: "galveston", details: "", sights: [], more_details: "", image: "../assets/galveston-island.jpg" }, { citySlug: "houston", details: "", sights: [], more_details: "", image: "../assets/houston.jpg" }, { citySlug: "san_antonio", details: "", sights: [], more_details: "", image: "../assets/san_antonio.jpg" } ];
修改City UI文件代码
方案1:配合调整后的数组结构
import { useRouter } from "next/router"; import { cityData } from "../api/dummydata"; export default function Service() { const router = useRouter(); // 把路由里的空格转成下划线,匹配数据中的citySlug const targetSlug = router.asPath.replace("/", "").replace(/\s+/g, "_"); // 筛选匹配的城市数据 const matchedCity = cityData.find(item => item.citySlug === targetSlug); // 兜底处理:未找到对应城市时的提示 if (!matchedCity) { return <div>未找到该城市数据</div>; } return ( <div> <h1>{matchedCity.citySlug.replace(/_/g, " ")}</h1> <img src={matchedCity.image} alt={matchedCity.citySlug} /> <p>{matchedCity.details}</p> {/* 按需渲染其他字段 */} </div> ); }
方案2:保留原对象结构
如果不想修改数据结构,修正Object.keys的用法即可,通过类型断言解决TypeScript类型错误:
import { useRouter } from "next/router"; import { cityData } from "../api/dummydata"; export default function Service() { const router = useRouter(); const targetSlug = router.asPath.replace("/", "").replace(/\s+/g, "_"); // 获取所有城市键名并做类型断言 const cityKeys = Object.keys(cityData) as Array<keyof typeof cityData>; // 匹配对应键名 const matchedKey = cityKeys.find(key => key === targetSlug); // 获取对应城市的数组数据,合并为单个对象 const matchedData = matchedKey ? Object.assign({}, ...cityData[matchedKey]) : null; if (!matchedData) { return <div>未找到该城市数据</div>; } return ( <div> <h1>{targetSlug.replace(/_/g, " ")}</h1> <img src={matchedData.image} alt={targetSlug} /> <p>{matchedData.details}</p> {/* 按需渲染其他字段 */} </div> ); }
内容的提问来源于stack exchange,提问作者Jamie Garcia
相关产品推荐
相关产品推荐

