React项目中Blog.js与PostDetails.js渲染异常及路由问题咨询
博客页面渲染异常与跳转功能修复方案
一、Blog页面仅显示Navbar和Footer的原因及修复
核心问题1:react-router-dom v6路由写法错误
你使用的是react-router-dom v6,但App.js中Route组件仍沿用v5的component属性,v6中必须用element属性指定渲染组件,这直接导致Blog和PostDetails组件无法被正确渲染。
核心问题2:Blog组件内嵌套路由写法错误
v6中不能在组件内直接使用Route标签,嵌套路由需要通过Outlet配合父路由的children配置实现,原Blog.js里的Route写法完全无效。
核心问题3:静态文件路径错误
create-react-app中静态资源需放在public文件夹下,原fetch('./data/posts.json')的相对路径会导致文件找不到,最终posts数组为空,PostList无内容。
修复代码:
修改App.js:
import Layout from "./components/layout/Layout"; import Blog from "./Blog"; import Home from "./pages/Home"; import Contact from "./pages/Contact"; import Navbar from "./components/layout/Navbar"; import { BrowserRouter as Router, Route, Routes } from "react-router-dom"; import PostDetails from "./components/PostDetails"; function App() { return ( <Router> <div> <h1>SME Analyst</h1> <div className="App"> <Navbar /> <Routes> <Route path="/" element={<Home />}/> {/* 改用element属性,同时配置嵌套路由 */} <Route path="/blog" element={<Blog />}> <Route path=":postId" element={<PostDetails />} /> </Route> <Route path="/contact" element={<Contact />}/> </Routes> <Layout /> </div> </div> </Router> ); } export default App;
修改Blog.js:
import React, { useState, useEffect } from 'react'; import { Outlet } from 'react-router-dom'; // 引入Outlet渲染嵌套路由 import PostList from './components/PostList'; const Blog = () => { const [posts, setPosts] = useState([]); useEffect(() => { // 改用绝对路径,确保public/data/posts.json存在 fetch('/data/posts.json') .then(response => { if (!response.ok) throw new Error('加载文章列表失败'); return response.json(); }) .then(data => setPosts(data)) .catch(err => console.error(err)); }, []); return ( <div> <h1>My Blog</h1> <PostList posts={posts} /> {/* 用Outlet渲染嵌套的PostDetails组件 */} <Outlet /> </div> ); }; export default Blog;
二、Post跳转功能的代码问题及修复
问题1:useNavigate用法错误
react-router-dom v6中,useNavigate返回的是直接调用的函数,不需要.push()方法,且原跳转路径posts.json/${post.id}与路由配置不匹配,应该跳转到/blog/:postId。
问题2:PostDetails获取参数方式错误
v6中无法直接通过props获取postId,需要用useParams钩子获取URL参数,同时要处理文章加载的异步状态和不存在的情况。
修复代码:
修改Post.js:
import { useNavigate } from 'react-router-dom'; const Post = ({ post }) => { const navigate = useNavigate(); const handleClick = () => { // 跳转到正确的路由路径 navigate(`/blog/${post.id}`); }; return ( <div onClick={handleClick} style={{ cursor: 'pointer' }}> <h2>{post.title}</h2> <p>{post.summary}</p> </div> ); }; export default Post;
修改PostDetails.js:
import React, { useState, useEffect } from 'react'; import { useParams } from 'react-router-dom'; const PostDetails = () => { const { postId } = useParams(); // 用useParams获取URL参数 const [post, setPost] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { fetch('/data/posts.json') .then(response => { if (!response.ok) throw new Error('无法获取文章数据'); return response.json(); }) .then(data => { const foundPost = data.find(item => item.id === parseInt(postId)); if (foundPost) { setPost(foundPost); } else { setError('文章不存在'); } setLoading(false); }) .catch(err => { setError(err.message); setLoading(false); }); }, [postId]); if (loading) return <div>加载中...</div>; if (error) return <div>错误:{error}</div>; if (!post) return <div>未找到该文章</div>; return ( <div> <h1>{post.title}</h1> <p>发布日期:{post.date}</p> <p>{post.body}</p> </div> ); }; export default PostDetails;
修改PostList.js:
移除无用的onPostClick参数,跳转逻辑已在Post组件内处理:
import React from 'react'; import Post from './Post'; const PostList = ({ posts }) => ( <div> {posts.map(post => ( <Post key={post.id} post={post} /> ))} </div> ); export default PostList;
内容的提问来源于stack exchange,提问作者Sren94
相关产品推荐
相关产品推荐

