React帖子详情页刷新时post属性未定义的问题求助
刷新React帖子详情页时出现
post.id未定义错误 我正在开发一个支持用户发布帖子、评论、点赞/取消点赞的React应用,正常跳转进入帖子详情页一切正常,但刷新页面时会出现post.id未定义的错误,移除post.id引用后又会出现post.title未定义,以此类推。附上App.js和PostDetail.js代码,求解决方法。
App.js代码
import './App.css'; import { BrowserRouter, Routes, Route } from 'react-router-dom'; import Navbar from './pages/Navbar'; import LoginPage from './pages/LoginPage'; import PostList from './posts/PostList'; import PostDetail from './posts/PostDetail'; import EditPost from './posts/EditPost'; import Home from './pages/Home'; function App() { return ( <BrowserRouter> <Navbar /> <div className="App"> <Routes> <Route path="/posts" element={<PostList />} /> <Route path="/posts/:id/edit" element={<EditPost/>} /> <Route path="/posts/:id" element={<PostDetail />} /> <Route path="/home" element={<Home />} /> <Route path="/" element={<LoginPage />} /> </Routes> </div> </BrowserRouter> ); } export default App;
PostDetail.js代码
import { useContext, useEffect, useState } from "react"; import { Link, useNavigate, useParams } from "react-router-dom"; import { ContentContext } from "../context/ContentContext"; import { UserContext} from "../context/UserContext"; import CommentList from "../comments/CommentList"; import { ErrorContext } from "../context/ErrorContext"; function PostDetail () { const { setErrors } = useContext(ErrorContext); const { user } = useContext(UserContext); const { contents, deletePost } = useContext(ContentContext); const id = parseInt(useParams().id); const post = contents.find(post => post.id === id); const navigate = useNavigate(); const [commentMode, setCommentMode] = useState(false); const openComment = () => setCommentMode(commentMode => !commentMode); const [liked, setLiked] = useState(false); const params = useParams(); useEffect(() => { fetch(`/posts/${post.id}/likes`) .then(resp => { if (resp.ok) { resp.json().then(data => { setLiked(data.liked) }) } }) .catch(error => { setErrors(error) }) }, [post, setErrors]) const handleLike = () => { fetch(`/posts/${post.id}/likes`, { method: 'POST', headers: { 'Content-Type': 'application/json', }, }) .then(resp => resp.json()) .then(data => { if (data.success) { setLiked(true); } }) .catch(error => { setErrors(error) }); } const handleUnlike = () => { fetch(`/posts/${post.id}/likes/${params.id}`, { method: 'DELETE', headers: { 'Content-Type': 'application/json', }, }) .then(resp => resp.json()) .then(data => { if (data.success) { setLiked(false); } }) .catch(error => { setErrors(error) }); } const onDeletePost = () => { fetch(`/posts/${post.id}`, { method: "DELETE", }) .then(resp => resp.json()) .then(deletePost(post.id)) .then(navigate(`/posts`)) } return ( <div> <div className="box-2"> <h1>{post.title}</h1> <h5>{post.creator.username}</h5> <p>{post.content}</p> {liked ? ( <button className="edit-btn" onClick={handleUnlike}>Unlike</button> ):( <button className="edit-btn" onClick={handleLike}>Like</button> )} <button className="edit-btn" onClick={openComment}>Comments</button> {user && user.username === post.creator?.username && ( <> <button className="edit-btn"><Link to={`/posts/${post.id}/edit`}>Edit</Link></button> <button className="edit-btn" onClick={onDeletePost}>Delete</button> </> )} <br /><br /> </div> <br /> <hr /> <br /> <div> {commentMode && <CommentList post={post}/>} </div> </div> ) } export default PostDetail;
问题原因&解决方法
核心原因
刷新页面时,全局ContentContext中的contents数组还没完成初始化(或者是空的),此时contents.find()找不到对应帖子,返回undefined,直接访问post.id、post.title这类属性就会触发未定义错误。
1. 快速修复:添加空状态判断
在PostDetail组件的return语句上方,先判断post是否存在,不存在时显示加载提示:
// 放在return语句上方 if (!post) { return <div>加载中...</div>; }
2. 彻底解决:优化数据获取逻辑
依赖全局Context的缓存数据在刷新时会丢失,更可靠的方式是在PostDetail组件中单独请求当前帖子的数据,不依赖全局缓存:
// 修改PostDetail的核心逻辑 function PostDetail () { const { setErrors } = useContext(ErrorContext); const { user } = useContext(UserContext); const { deletePost } = useContext(ContentContext); const { id } = useParams(); const numericId = parseInt(id); const [post, setPost] = useState(null); const navigate = useNavigate(); const [commentMode, setCommentMode] = useState(false); const [liked, setLiked] = useState(false); // 单独请求当前帖子数据 useEffect(() => { fetch(`/posts/${numericId}`) .then(resp => resp.json()) .then(data => setPost(data)) .catch(error => setErrors(error)); }, [numericId, setErrors]); // 等post加载完成后再请求点赞状态 useEffect(() => { if (!post) return; fetch(`/posts/${post.id}/likes`) .then(resp => { if (resp.ok) { resp.json().then(data => setLiked(data.liked)) } }) .catch(error => setErrors(error)) }, [post, setErrors]) // 空状态判断 if (!post) { return <div>加载中...</div>; } // 其余handleLike、handleUnlike等逻辑保留,注意修复以下小问题 }
3. 修复其他细节错误
handleUnlike路径错误:当前路径是/posts/${post.id}/likes/${params.id},这里的params.id是帖子ID,需替换为点赞记录ID;如果后端接口支持根据用户+帖子ID取消点赞,可改为/posts/${post.id}/likesonDeletePost链式调用错误:then(deletePost(post.id))会直接执行函数,需改成回调形式:
.then(() => deletePost(post.id)) .then(() => navigate(`/posts`))
内容的提问来源于stack exchange,提问作者janestack
相关产品推荐
相关产品推荐

