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

React项目中如何修正代码实现博客详情页内容展示?

问题描述

我是React新手,离开技术领域许久后正在学习Java,非常感谢您的帮助。请问如何修正我提供的代码,使博客详情页能够按预期展示文章的标题、作者、正文、日期等内容?

现有代码

BlogDetail.js

import React, { useState, useEffect } from "react";
import axios from "axios";
import { Link } from "react-router-dom";

function BlogDetail() {
  const [setBlogs] = useState([]);

  useEffect(() => {
    const fetchBlogs = async () => {
      try {
        const res = await axios.get(`http://localhost:8000/api/blog/`);
        setBlogs(res.data);
      } catch (err) {}
    };

    fetchBlogs();
  }, []);

  return (BlogPost) => (
    <div className="container-m-3">
      <article>
        <Link to={`/blog/${BlogPost.slug}`} className="stretched-link">
          {BlogPost.title}
        </Link>
        <h1 className="display-2">{BlogPost.title}</h1>
        <h2 className="text-muted mt-3">
          Category: {capitalizeFirstLetter(BlogPost.category)}
        </h2>
        <h4>
          {BlogPost.month} {BlogPost.day}
        </h4>
        <p>Written by {BlogPost.author}</p>
        <div>{BlogPost.body}</div>
        <hr />
        <p className="lead mb-5">
          <Link
            to="http://localhost:8000/api/blog/"
            className="font-weight-bold"
          >
            Front Page
          </Link>
        </p>
      </article>
    </div>
  );
}

const capitalizeFirstLetter = (word) => {
  if (word) return word.charAt(0).toUpperCase() + word.slice(1);
  return "";
};

export default BlogDetail;

App.js

import React from 'react';
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
import Layout from './hocs/Layout';
import Home from './components/Home';
import Blog from './components/Blog';
import BlogDetail from './components/BlogDetail';
import Category from './components/Category';

const App = () => (
    <Router>
        <Layout>
            <Routes>
                <Route path='/' element={<Home/>} />
                <Route path='/blog' element={<Blog/>} />
                <Route path='/blog/:id' element={<BlogDetail/>} />
                <Route path='/category/:id' element={<Category/>} />
            </Routes>
        </Layout>
    </Router>
);

export default App;

修正方案

你的代码存在几个核心问题,直接修改如下:

1. 修正BlogDetail.js

import React, { useState, useEffect } from "react";
import axios from "axios";
import { Link, useParams } from "react-router-dom"; // 新增useParams导入

function BlogDetail() {
  // 改为单个博客的状态,初始值为null
  const [blog, setBlog] = useState(null);
  // 获取URL中的id参数
  const { id } = useParams();

  useEffect(() => {
    const fetchBlog = async () => {
      try {
        // 请求单个博客的接口,替换为你后端实际的单篇博客接口
        const res = await axios.get(`http://localhost:8000/api/blog/${id}`);
        setBlog(res.data);
      } catch (err) {
        console.error('获取博客详情失败:', err); // 新增错误日志
      }
    };

    if (id) { // 确保id存在再请求
      fetchBlog();
    }
  }, [id]); // 依赖项添加id,参数变化时重新请求

  // 处理加载状态
  if (!blog) {
    return <div className="container mt-3">加载中...</div>;
  }

  // 直接返回JSX,而非返回函数
  return (
    <div className="container mt-3"> {/* 修正class名:container-m-3 → container mt-3 */}
      <article>
        <h1 className="display-2">{blog.title}</h1>
        <h2 className="text-muted mt-3">
          Category: {capitalizeFirstLetter(blog.category)}
        </h2>
        <h4>
          {blog.month} {blog.day}
        </h4>
        <p>Written by {blog.author}</p>
        {/* 如果body是HTML内容,用dangerouslySetInnerHTML渲染,否则直接输出 */}
        <div dangerouslySetInnerHTML={{ __html: blog.body }} />
        <hr />
        <p className="lead mb-5">
          <Link to="/blog" className="font-weight-bold"> {/* 改为前端路由,而非直接跳转到API地址 */}
            Front Page
          </Link>
        </p>
      </article>
    </div>
  );
}

const capitalizeFirstLetter = (word) => {
  if (word) return word.charAt(0).toUpperCase() + word.slice(1);
  return "";
};

export default BlogDetail;

2. 调整App.js(可选,根据后端接口决定)

如果你的后端用slug而非id来标识单篇博客,需要把路由改为:

<Route path='/blog/:slug' element={<BlogDetail/>} />

同时在BlogDetail.js中把const { id } = useParams();改为const { slug } = useParams();,请求接口改为http://localhost:8000/api/blog/${slug}。

关键修改点说明

  • 状态管理修正:详情页只需要单个博客数据,所以把数组状态改为单个对象,初始值设为null。
  • 获取URL参数:通过useParams获取路由中的id/slug,用于请求对应博客。
  • 接口请求修正:请求单篇博客的接口,而非所有博客列表。
  • 组件返回值修正:React组件直接返回JSX,不能返回函数。
  • 加载状态处理:在博客数据未加载完成时显示加载提示,避免渲染undefined属性报错。
  • 路由跳转修正:把跳转到API地址的链接改为前端路由/blog,保持单页应用的跳转逻辑。
  • HTML内容渲染:如果博客正文是HTML格式,用dangerouslySetInnerHTML渲染,否则直接输出即可。

内容的提问来源于stack exchange,提问作者Ben

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 18:24:32