Next.js TypeScript动态路由获取单篇文章返回Undefined求助
Next.js TypeScript 单篇文章页面 undefined 问题排查与解决
问题概述
使用Next.js TypeScript搭建博客,已实现从MongoDB获取所有文章,但单篇文章页面无法正常加载,控制台打印singlePost为undefined。API接口测试正常,此前Next.js JavaScript版本可正常运行,且.env中apiDomain配置正确。
核心问题分析与修复步骤
1. API路由路径与参数解构错误
你的route.ts注释标注为GET /api/posts,但单篇文章的API路由应对应/api/posts/[id],因此文件需放在app/api/posts/[id]/route.ts路径下。同时,Next.js 13+的API路由函数需要正确解构params并添加类型定义,否则会导致params.id无法正确获取。
修改后的route.ts:
import { connectDB } from "@/database/dbConfig"; import Post from "@/models/postModel"; import { NextRequest, NextResponse } from "next/server"; // GET /api/posts/[id] export const GET = async (request: NextRequest, { params }: { params: { id: string } }) => { try { await connectDB(); const post = await Post.findById(params.id); if (!post) return NextResponse.json({ message: "Post Not Found" }, { status: 404 }); return NextResponse.json(post, { status: 200 }); } catch (error) { console.error(error); return NextResponse.json({ message: "Something went wrong" }, { status: 500 }); } };
2. 组件中useEffect触发条件错误
初始状态下singlePost是undefined,但你的判断条件是if (singlePost === null),导致组件挂载时不会触发数据请求。同时,数据请求开始时未设置loading为true,逻辑不完整。
修改后的SinglePostPage组件:
import { useParams } from "next/navigation"; import { useState, useEffect } from "react"; import fetchSinglePost from "@/utils/fetchSinglePost"; // 假设你有Post类型定义 import type Post from "@/models/postModel"; const SinglePostPage = () => { const { id } = useParams(); const [singlePost, setSinglePost] = useState<Post | undefined>(undefined); const [loading, setLoading] = useState(true); useEffect(() => { const fetchPost = async () => { if (!id) return; setLoading(true); try { const postData = await fetchSinglePost(id as string); setSinglePost(postData); } catch (error) { console.error("Error fetching post:", error); } finally { setLoading(false); } }; // 当id存在且singlePost未加载时触发请求 if (id && !singlePost) { fetchPost(); } }, [id, singlePost]); if (loading) return <div>Loading...</div>; if (!singlePost) return <div>Post not found</div>; return ( <div className="singlepostPage"> <h2>{singlePost.title}</h2> <div>{singlePost.content}</div> </div> ); }; export default SinglePostPage;
3. 确保apiDomain正确暴露给客户端
客户端组件中无法直接读取未加NEXT_PUBLIC_前缀的环境变量,需确保.env中的变量名为NEXT_PUBLIC_API_DOMAIN,并在fetchSinglePost中正确引用:
修改后的fetchSinglePost函数:
import type Post from "@/models/postModel"; const apiDomain = process.env.NEXT_PUBLIC_API_DOMAIN; async function fetchSinglePost(id: string): Promise<Post> { try { if (!apiDomain) { throw new Error("API domain not configured"); } const res = await fetch(`${apiDomain}/api/posts/${id}`); if (!res.ok) { throw new Error(`Failed to fetch post: ${res.statusText}`); } return await res.json(); } catch (error) { console.error("Fetch single post error:", error); throw error; } } export default fetchSinglePost;
额外检查点
- 确认MongoDB中的
_id是字符串类型,或者在查询时正确处理ObjectId(如果你的postModel中_id定义为ObjectId,需确保传入的id能被findById识别)。 - 检查网络请求是否真的发送(通过浏览器开发者工具的Network标签),确认请求URL和参数是否正确。
内容的提问来源于stack exchange,提问作者Behnam
相关产品推荐
相关产品推荐

