Next.js动态页面导航出现404错误求助排查
Next.js动态页面导航404问题修复
问题核心
开发车辆详情动态页时,点击列表页链接跳转后始终返回404,无其他报错。尝试将_id类型改为字符串后,VSCode保存时会自动恢复为number类型。
代码分析与问题点
1. 动态路由文件结构错误
Next.js App Router要求动态路由必须遵循app/[路由段]/page.tsx的结构。如果车辆详情页未放在app/vehicles/[vehicleId]/page.tsx路径下,会直接返回404。
2. 类型定义不匹配
Vehicle类型中_id被定义为number,但后端API返回的_id(通常是MongoDB的ObjectId)是字符串类型。这会导致:
- 链接拼接时
vehicle._id(number)转字符串可能出现格式问题 - VSCode的类型检查或格式化工具(如Prettier)会自动将手动修改的
string类型恢复为number
3. 数据获取与组件渲染不匹配
getVehicleDetail函数获取的是单个车辆数据,但VehicleDetails组件却按数组处理,调用map方法会导致渲染异常VehiclePage传递给VehicleDetails的是单个车辆的Promise,却被当作数组Promise接收
修复步骤
步骤1:确认动态路由文件结构
确保项目目录结构如下:
app/ ├── vehicles/ │ ├── [vehicleId]/ │ │ └── page.tsx # 车辆详情页必须放在此路径下 └── ...
步骤2:修正类型定义
将Vehicle类型的_id改为string,匹配API返回的ObjectId格式:
// 修正后的Vehicle类型 type Vehicle = { _id: string; name: string; pictures: string; description: string; colour: string; transmission: string; type: string; seat: number; price: number; date: string; createdBy: string; };
解决VSCode自动恢复类型的问题
检查项目中的Prettier或TypeScript配置:
- 若为Prettier自动格式化导致,可在
.prettierrc中添加规则禁用类型自动修改 - 若为TypeScript类型推断问题,给
getVehicleDetail明确添加返回类型标注:
export default async function getVehicleDetail(vehicleId: string): Promise<Vehicle | undefined> { const res = await fetch( `https://brainy-clothes-fish.cyclic.app/api/v1/vehicles/${vehicleId}`, { next: { revalidate: 60 } } ); if (!res.ok) return undefined; return res.json() as Promise<Vehicle>; }
步骤3:修正组件数据处理逻辑
修正VehicleDetails组件
因为获取的是单个车辆,无需map数组,直接渲染单条数据:
type Props = { vehicle: Vehicle | undefined; }; export default function VehicleDetails({ vehicle }: Props) { if (!vehicle) return <div>车辆不存在</div>; return ( <article> <h2>{vehicle.name}</h2> {/* 其他车辆信息渲染 */} </article> ); }
修正VehiclePage组件
直接获取单个车辆数据,传递给VehicleDetails:
import getVehicleDetail from "@/lib/getVehicleDetails"; import VehicleDetails from "./components/VehicleDetails"; type Params = { params: { vehicleId: string; }; }; export default async function VehiclePage({ params: { vehicleId } }: Params) { const vehicle = await getVehicleDetail(vehicleId); return <VehicleDetails vehicle={vehicle} />; }
步骤4:确认列表页链接正确性
给列表项添加唯一key,确保链接拼接正确:
// HomeMainBody组件中 {vehicles.map((vehicle) => { return ( <div key={vehicle._id}> <VehicleCard vehicle={vehicle} /> <Link href={`/vehicles/${vehicle._id}`}>{vehicle.name}</Link> </div> ); })}
验证修复
- 重启Next.js开发服务器
- 点击列表页车辆链接,确认能正常跳转并展示详情数据
- 若VSCode仍自动修改类型,可在类型定义处添加
// @ts-ignore临时忽略,或调整IDE格式化设置
内容的提问来源于stack exchange,提问作者coderx
相关产品推荐
相关产品推荐

