我有 singlePost 组件,现在加载了帖子,我创建了另一个组件 Comments,当我从 Comment 部分添加或删除评论时,它不会重新渲染以向我显示结果,而是在刷新浏览器时工作。
我正在尝试在帖子上添加和删除评论,因此我为该评论创建了另一个组件,但我的评论不会立即添加和删除,而是在刷新页面时添加或删除。
import "./singlepost.css";
import axios from "axios";
import React, { useEffect, useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import { Link, useLocation } from "react-router-dom";
import { favPost } from "../../redux/userSlice";
import Comments from "../comments/Comments";
export default function SinglePost() {
const location = useLocation();
const path = location.pathname.split("/")[2];
const [post, setPost] = useState({});
const PF = "http://localhost:5000/images/";
const user = useSelector((state) => state.user.currentUser);
console.log(user);
const [title, setTitle] = useState("");
const [desc, setDesc] = useState("");
const [comments, setComments] = useState([]);
const [replies, setReplies] = useState([]);
const [updateMode, setUpdateMode] = useState(false);
const [isLiked, setIsLiked] = useState(false);
const [iconColor, setIconColor] = useState("");
const [like, setLike] = useState(0);
const dispatch = useDispatch();
// const [unliked, setUnliked] = useState("");
//Getting Single Post
useEffect(() => {
const getPost = async () => {
const res = await axios.get("/posts/" + path);
setPost(res.data);
setTitle(res.data.title);
setDesc(res.data.desc);
setLike(res.data.likes.length);
setComments(res.data.comments);
if (user && user.favPosts.includes(post._id)) {
setIconColor("red");
}
};
getPost();
}, []);
useEffect(() => {
setIsLiked(post?.likes?.includes(user._id));
}, [user._id, post.likes, post._id]);
const handleDelete = async () => {
try {
await axios.delete("/posts/" + path, {
headers: { token: "Bearer " + user.token },
data: { username: user.username },
});
window.location.replace("/");
} catch (err) {}
};
const handleUpdate = async () => {
try {
await axios.put(
`/posts/${post._id}`,
{
username: user.username,
title,
desc,
},
{ headers: { token: "Bearer " + user.token } }
);
setUpdateMode(false);
} catch (err) {}
};
const handleFavourites = async (e) => {
e.preventDefault();
try {
const response = await axios.post(
"/user/favPosts",
{ postId: post._id },
{ headers: { token: "Bearer " + user.token } }
);
dispatch(favPost(response.data));
if (user.favPosts.includes(post._id)) {
setIconColor("");
} else {
setIconColor("red");
}
} catch (err) {
console.log(err);
}
};
const likeHandler = async (e) => {
console.log(user.token);
try {
await axios.put(
`/posts/${post._id}/like`,
{},
{ headers: { token: "Bearer " + user.token } }
);
} catch (err) {
console.log(err);
}
console.log("like", like);
setLike(isLiked ? like - 1 : like + 1);
setIsLiked(!isLiked);
};
const handleAddComment = (newlyComment) => {
setComments((prevComment)=>({
...prevComment, newlyComment
}))
};
const handleDeleteComment = (deletedCommentId) => {
setComments(comments.filter((item) => item._id !== deletedCommentId));
};
return (
<div className="singlePost">
<div className="singlePostWrapper">
<div className="singlePostDetails">
{post.photo && (
<img src={PF + post.photo} alt="" className="singlePostImg" />
)}
<div className="postlikeFavouriteWrapper">
<div className="postLikeFavourite">
<span
className="like"
style={{ color: iconColor }}
onClick={handleFavourites}
>
<i class="fa-solid fa-heart"></i>
</span>
<span className="thumbsUp" onClick={likeHandler}>
<i class="fa-solid fa-thumbs-up"></i>
</span>
<span className="postLikeCounter">{like} people like it</span>
</div>
<div className="authorDetails">
<span className="singlePostAuthor">
<Link to={`/?user=${post.username}`} className="singlePostLink">
Author:<b>{post.username}</b>
</Link>
<span className="singlePostDate">
{new Date(post.createdAt).toDateString()}
</span>
</span>
</div>
</div>
{updateMode ? (
<input
type="text"
value={title}
className="singlePostTitleInput"
autoFocus
onChange={(e) => setTitle(e.target.value)}
/>
) : (
<div className="titleandicon">
<div>
<h1 className="singlePostTitle">{title}</h1>
</div>
{post.username === user?.username && (
<div className="singlePostEdit">
<i
className=" singlePostIcon fa-solid fa-pen-to-square"
onClick={() => setUpdateMode(true)}
></i>
<i
className=" singlePostIcon fa-solid fa-trash-can"
onClick={handleDelete}
></i>
</div>
)}
</div>
)}
</div>
<div className="singlePostInfo">
{updateMode ? (
<textarea
className="singlePostDescInput"
value={desc}
onChange={(e) => setDesc(e.target.value)}
></textarea>
) : (
<>
<div className="postFeatures">
<p className="singlePostDesc">{desc}</p>
</div>
</>
)}
{updateMode && (
<button className="singlePostButton" onClick={handleUpdate}>
Update
</button>
)}
</div>
</div>
<Comments post={post} onDeleteComment={handleDeleteComment} onAddComment={handleAddComment} />
</div>
);
}
评论.jsx
import "./comments.css";
import axios from 'axios';
import React, { useEffect, useState } from 'react';
import { useSelector } from 'react-redux';
import { useLocation } from "react-router-dom";
const Comments = (props) => {
const user = useSelector((state) => state.user.currentUser);
const [post, setPost] = useState({});
const [comments, setComments] = useState([]);
const [newComment, setNewComment] = useState("");
const [commentUpdateMode, setCommentUpdateMode] = useState(false);
const [reply, setReply] = useState("");
const [replyFormStates, setReplyFormStates] = useState({});
const handleCommentSubmission = async (e) => {
e.preventDefault();
try {
const commented = await axios.put(
`/posts/comments/${props.post._id}`,
{ newComment },
{ headers: { token: "Bearer " + user.token } }
);
const newlyComment = commented.data.comments;
console.log("commented", commented);
console.log("ccc", newComment)
props.onAddComment(newlyComment);
} catch (err) {
console.log(err);
}
e.target.reset();
};
const handleCommentDeleteFor = async (deleteCommentId) => {
try {
await axios.put(
`/posts/deletecomment/${props.post._id}`,
{ deleteCommentId },
{ headers: { token: "Bearer " + user.token } }
);
props.onDeleteComment(deleteCommentId)
} catch (err) {
console.log(err);
}
};
const handleCommentReply = async (id) => {
setReplyFormStates((prevState) => ({
...prevState,
[id]: true, // Open reply form for the specific comment
}));
console.log(replyFormStates);
};
const handleCommentSubmit = async (commentId, reply) => {
// Handle the submission of the reply and update the comments state
// Reset the reply form state for the specific comment
const replyText = await axios.put(
"/posts/replycomment",
{ postId: post._id, commentId: commentId, reply: reply },
{ headers: { token: "Bearer " + user.token } }
);
console.log("rr", replyText);
setComments(replyText.data.comments);
console.log("ij", commentId);
setReplyFormStates((prevState) => ({
...prevState,
[commentId]: false,
}));
};
return (
<div>
<div className="postComment">
<form onSubmit={handleCommentSubmission}>
<input
type="text"
placeholder="Add Comments"
name="postCommentField"
className="postCommentsArea"
onChange={(e) => setNewComment(e.target.value)}
/>
<hr/>
<button type="submit" className="postCommentbtn">
Post Your Comment
</button>
</form>
</div>
<div className="showComments">
{props?.post?.comments?.map((item) => {
const isReplyFormOpen = replyFormStates[item._id];
return (
<>
<span className="commentorname" key={item._id}> {item.postedBy.username}</span>
<span className="commentDate">
{new Date(item.created).toDateString()}
</span>
<div className="commentText">
{item.text} <i class="fa-solid fa-thumbs-up"></i>
<i className=" singlePostIcon fa-solid fa-trash-can"
onClick={() => handleCommentDeleteFor(item._id)}
></i>
<i className=" singlePostIcon fa-solid fa-pen-to-square"
onClick={() => setCommentUpdateMode(true)}
></i>
<span
className="commentsreply"
onClick={() => handleCommentReply(item._id)}
>
reply
</span>
{/* <span>{item.replies.message}</span> */}
<div className="showsreplies">
{item.replies.map((rep) => {
return (
<div>
<span className="replies">{rep.message}</span>
<span className="replierName">{rep.userId.username}</span>
</div>
);
})}
</div>
{isReplyFormOpen && (
<form>
<input
type="text"
onChange={(e) => setReply(e.target.value)}
/>
<button
type="submit"
onClick={(e) => {
e.preventDefault();
handleCommentSubmit(item._id, reply);
}}
>
Submit Reply
</button>
</form>
)}
</div>
</>
);
})}
</div>
</div>
)
}
export default Comments
注意 - 我是新手,可能是错的
尝试在 useEffect 的依赖数组中添加一些内容,这将触发重新获取您的帖子数据,然后您将获得更新的数据而无需刷新。
就像从第一个文件中将 getPost 添加为 useEffect 中的依赖项 -
useEffect(() => {
const getPost = async () => {
const res = await axios.get("/posts/" + path);
setPost(res.data);
setTitle(res.data.title);
setDesc(res.data.desc);
setLike(res.data.likes.length);
setComments(res.data.comments);
if (user && user.favPosts.includes(post._id)) {
setIconColor("red");
}
};
getPost();
}, [getPost]);
如果陷入循环,则添加其他内容以触发重新fetech