I am creating an app where users can post, comment, like, and unlike another user's post. Everything works great but while I am in a post and refresh that page, I get an error that the id in post.id is undefined. I then remove the id from post.id -- I get another error, title in post.title is undefined and it goes on.
I am fairly new to programming so this might be a 'duhh' thing but I'm so frustrated because I don't get what's going on.
Any help is really appreciated.
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;
I believe the problem is somewhere in these two files.
Your
postis empty because you have not fetched it yet, or it doesn't exist.const post = contents.find(post => post.id === id);returnsundefinedwhen id is not found in the array.Just check if post exists before rendering it:
Also, hooks should be utilized directly within the component body. Wrapping them in additional functions breaks the pattern. (
use...is a special prefix in React)So instead of:
Do: