如何在点赞数变化时实时渲染点赞按钮的计数?
问题描述
我已创建一个点赞按钮,点击后会将事件发送至后端以更新帖子,后端会返回更新后的帖子,但我无法渲染更新后的帖子。
帖子加载完成后会作为参数传入该页面
PostCard组件代码
import React, { Fragment, useEffect, useState } from 'react'; import "./PostCard.css"; import Person4Icon from '@mui/icons-material/Person4'; import FavoriteIcon from '@mui/icons-material/Favorite'; import HeartBrokenIcon from '@mui/icons-material/HeartBroken'; import ForumOutlinedIcon from '@mui/icons-material/ForumOutlined'; import { Link } from 'react-router-dom'; import { likeDislike } from '../../actions/postAction'; import { useSelector, useDispatch } from "react-redux"; const PostCard = ({post}) => { // console.log(post); const dispatch = useDispatch(); const { like } = useSelector((state) => state.likePost); const { isAuthenticated, user } = useSelector((state) => state.user); const [likeCount, setLikeCount] = useState(Object.keys(post.hearts).length); var isLiked=false; if(isAuthenticated){ isLiked = Boolean(post.hearts[user._id]); } const likes = () => { dispatch(likeDislike(post._id)); setLikeCount(Object.keys(post.hearts).length); console.log(like.hearts); console.log(Object.keys(like.hearts).length); } const dislikes = () => { dispatch(likeDislike(post._id)) } return ( <Fragment> <div className='card'> <div className='profile_icon'><Person4Icon style={{color: post.avatarColor}} /></div> <div className='post'> <Link className='card_head' to={`/comment/${post._id}`}> <h4 style={{color:"orange"}} >{post.userName}</h4> <p>{post.post}</p> </Link> <div className='post_footer'> <Link className='card_head' to={`/comment/${post._id}`}> <div className='post_footer_button'> <ForumOutlinedIcon/> <span className='number'>{post.comments.length}</span> </div> </Link> <div className='post_footer_button'> <HeartBrokenIcon onClick={dislikes}/> <span className='number'>{post.condolences.length}</span> </div> <div className='post_footer_button'> <FavoriteIcon onClick={likes}/> <span className='number'>{likeCount}</span> </div> </div> </div> </div> <div className='break'> </div> </Fragment> ) } export default PostCard
点赞事件的Dispatch Action部分
//Likes Dislikes export const likeDislike = (id) => async (dispatch) => { try { dispatch({ type: LIKE_POST_REQUEST }); const config = { headers: { "Content-Type": "application/json" } }; const { data } = await axios.put(`/social/like`, {id}, config); console.log(data); dispatch({ type: LIKE_POST_SUCCESS, payload: data.updatedPost, }); } catch (error) { dispatch({ type: LIKE_POST_FAIL, payload: error.response.data.message, }); } }
更新点赞帖子的Reducer
export const likePostReducer = (state = {like: {}}, action) => { switch (action.type) { case LIKE_POST_REQUEST: return { ...state, loading: true, }; case LIKE_POST_SUCCESS: return { loading: false, like: action.payload, }; case LIKE_POST_FAIL: return { loading: false, error: action.payload, }; case CLEAR_ERRORS: return { ...state, error: null, }; default: return state; } };
后端更新帖子的代码
exports.likePost = catchAsyncErrors(async(req,res,next) => { // console.log(req.body); const {id} = req.body; const post = await Post.findById(id); const user = await User.findById(req.user._id); const isLiked = post.hearts.get(user._id); if (isLiked) { post.hearts.delete(user._id); } else { post.hearts.set(user._id, true); } const updatedPost = await Post.findByIdAndUpdate( id, { hearts: post.hearts }, { new: true } ); res.status(200).json({ success:true, updatedPost, }); });
PostCard的父组件(Home组件)
import React, { Fragment, useEffect } from 'react'; import "./Home.css"; import PostCard from '../Layout/PostCard'; import CreatePost from '../Layout/CreatePost'; import { getPosts, clearErrors } from '../../actions/postAction'; import { useSelector, useDispatch } from "react-redux"; import {toast} from "react-toastify"; import Loader from "../Loader/Loader"; import { CREATE_POST_RESET } from '../../constants/postConstants'; import AddIcon from '@mui/icons-material/Add'; import { useNavigate } from "react-router-dom"; const Home = () => { const dispatch = useDispatch(); const navigate = useNavigate(); const { loading, error, posts } = useSelector((state) => state.posts); const { success } = useSelector((state) => state.createPost); const { isAuthenticated } = useSelector((state) => state.user); // console.log(user); const open = () => { if(isAuthenticated===false){ toast.error("Login first"); } if(isAuthenticated){ navigate("/createPost"); } } useEffect(() => { if(error){ toast.error(error); dispatch(clearErrors()); } if (success) { toast.success("Posted"); dispatch({ type: CREATE_POST_RESET }); } dispatch(getPosts()); },[dispatch, success, error]); return ( <Fragment> {loading ? ( <Loader/> ) : ( <Fragment> <div className='home'> <div className='home_left'> <div className='home_heading'> <h4>Try something here</h4> </div> <div> {posts && posts.map((post) => { return( <PostCard key={post._id} post={post} /> ); })} </div> </div> <div className='home_right'> <CreatePost/> </div> </div> {/* FLOATING BUTTON */} <div className='floating_button'> <button onClick={open}> <AddIcon/> </button> </div> </Fragment> )} </Fragment> ) } export default Home;
内容的提问来源于stack exchange,提问作者Atulya Jaiswal
相关产品推荐
相关产品推荐

