You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在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配置(必做)

  1. 安装依赖:
pip install django-cors-headers
  1. 修改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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 03:45:32