在NextJS 13中基于Django后端实现Post详情页数据获取
解决方案
核心问题分析
你的代码存在3个关键错误:
- 动态路由参数获取方式错误:你用
useSearchParams()尝试获取路径参数,但useSearchParams是用来获取URL中?key=value格式的查询参数的,而动态路由[id]的参数属于路径参数,需要用正确方式获取。 - 未用
useEffect包裹数据请求:直接在组件顶层调用fetchData()会导致组件每次渲染都重复发起请求,引发无限循环,同时可能导致数据获取时机错误。 - Tailwind样式类名错误:
font-6xl、font-red-800不符合Tailwind CSS命名规范,应该是text-6xl(控制字体大小)和text-red-800(控制字体颜色)。
此外,需确保Django后端配置CORS允许http://127.0.0.1:3000的请求,否则会出现跨域错误。
修正后的客户端组件版本
将[id]/page.tsx修改为以下内容:
'use client'; // 标记为客户端组件 import React, { useEffect, useState } from 'react'; import axios, { AxiosResponse } from 'axios'; import { useParams } from 'next/navigation'; interface Post { id: number; title: string; image_url: string | null; content: string; } const PostDetail: React.FC = () => { const [post, setPost] = useState<Post | null>(null); const [loading, setLoading] = useState(true); const [error, setError] = useState<string | null>(null); const params = useParams<{ id: string }>(); const id = params.id; useEffect(() => { const fetchData = async () => { if (!id) return; setLoading(true); try { const response: AxiosResponse<Post> = await axios.get(`http://127.0.0.1:8000/blog/api/posts/${id}/`); setPost(response.data); setError(null); } catch (err) { setError('获取文章详情失败'); console.error('Error fetching data:', err); } finally { setLoading(false); } }; fetchData(); }, [id]); if (loading) { return <div>Loading...</div>; } if (error || !post) { return <div>{error || '文章不存在'}</div>; } return ( <div className="max-w-4xl mx-auto p-6"> <h1 className='text-6xl text-red-800 mb-4'>{post.title}</h1> {post.image_url && <img src={post.image_url} alt={post.title} className="w-full h-auto mb-6 rounded" />} <div className="prose max-w-none"> {post.content} </div> </div> ); }; export default PostDetail;
更优方案:服务器组件版本(NextJS 13推荐)
App Router默认支持服务器组件,无需客户端状态和hooks,代码更简洁:
import axios from 'axios'; interface Post { id: number; title: string; image_url: string | null; content: string; } // 服务器组件直接接收params参数 async function PostDetail({ params }: { params: { id: string } }) { const { id } = params; try { const response = await axios.get<Post>(`http://127.0.0.1:8000/blog/api/posts/${id}/`); const post = response.data; return ( <div className="max-w-4xl mx-auto p-6"> <h1 className='text-6xl text-red-800 mb-4'>{post.title}</h1> {post.image_url && <img src={post.image_url} alt={post.title} className="w-full h-auto mb-6 rounded" />} <div className="prose max-w-none"> {post.content} </div> </div> ); } catch (error) { console.error('Error fetching post:', error); return <div className="max-w-4xl mx-auto p-6">文章不存在或获取失败</div>; } } export default PostDetail;
Django CORS配置(必做)
- 安装依赖:
pip install django-cors-headers
- 修改
settings.py:
INSTALLED_APPS = [ # ... 'corsheaders', # ... ] MIDDLEWARE = [ # 必须放在CommonMiddleware之前 'corsheaders.middleware.CorsMiddleware', 'django.middleware.common.CommonMiddleware', # ... ] # 允许的源 CORS_ALLOWED_ORIGINS = [ "http://127.0.0.1:3000", ]
内容的提问来源于stack exchange,提问作者Filip Kania
相关产品推荐
相关产品推荐

