为什么我的子组件在添加和删除注释后没有重新渲染

问题描述 投票:0回答:1

我有 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
components state refresh render parent
1个回答
0
投票

注意 - 我是新手,可能是错的

尝试在 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

© www.soinside.com 2019 - 2024. All rights reserved.