You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ReactJS/MERN栈单帖子点赞数更新异常求助

MERN栈CRUD应用点赞功能前端显示问题修复方案

问题概述

在MERN栈CRUD应用中实现单帖点赞功能时,前端出现异常:创建多个帖子后,点击其中一个的点赞按钮,除该帖子外其余所有帖子的点赞数均变为0;刷新页面后后端数据显示正常,但再次点击点赞按钮问题复现。

问题根源分析

  1. 全局点赞状态错误:使用单个布尔值liked控制所有帖子的点赞显示逻辑,点击任意帖子后,所有帖子都会切换到likes数组的数值,而likes初始化为全0数组,导致未点击的帖子显示0。
  2. 点赞数组初始化逻辑错误:组件每次渲染时initLikes都会被重新创建为全0数组,更新点赞时直接基于这个全0数组修改,覆盖了其他帖子的点赞数。
  3. 帖子列表更新逻辑错误:更新列表时错误地将匹配ID的帖子替换为ID字符串,而非更新后的完整帖子数据。

修复方案

修改ExperienceLikes组件

import React, { useState, useEffect } from 'react'
import Axios from 'axios';
import Space from './images/space.jpg'

function ExperienceLikes({ setListExperience, listExperience, picClicked }) {
    // 初始化点赞数组为各帖子当前的点赞数
    const [likes, setLikes] = useState(() => 
        listExperience.map(item => item.likeCount)
    )
    // 用对象存储每个帖子的点赞状态,键为帖子ID,实现单帖独立控制
    const [likedPosts, setLikedPosts] = useState({})

    // 当帖子列表更新时,同步更新点赞数组
    useEffect(() => {
        setLikes(listExperience.map(item => item.likeCount))
    }, [listExperience])

    const cardStyles = {
        background: "#ffffff",
        display: "flex",
        flexDirection: "column",
        justifyContent: "center",
        width: "161px",
        height: "180px",
        marginLeft: "30px",
        marginRight: "30px",
        marginTop: "20px",
        position: "relative",
    }

    const updateLike = (id, index) => {
        // 可选:防止重复点赞
        if (likedPosts[id]) return;
        
        Axios.put(`http://localhost:9001/${id}/likePost`)
            .then((response) => {
                // 正确更新帖子列表中的点赞数
                setListExperience(previous => 
                    previous.map(post => 
                        post._id === id 
                            ? { ...post, likeCount: response.data.likeCount } 
                            : post
                    )
                )
                // 标记当前帖子已点赞
                setLikedPosts(prev => ({ ...prev, [id]: true }))
                // 更新点赞数组对应位置的数值
                setLikes(prev => {
                    const newLikes = [...prev];
                    newLikes[index] = response.data.likeCount;
                    return newLikes;
                })
            })
    }

    const deletePost = (id) => {
        Axios.delete(`http://localhost:9001/${id}/delete`)
            .then(() => {
                setListExperience(listExperience.filter(post => post._id !== id))
                // 删除帖子后同步移除其点赞状态
                setLikedPosts(prev => {
                    const newState = { ...prev };
                    delete newState[id];
                    return newState;
                })
            })
    }

    return (
        <>
            {listExperience.map((post, index) => 
                <div key={post._id} className={`experience--card`} style={cardStyles}>
                    <div className='locate'>
                        {post.location}
                    </div>
                    <div className='image' style={{ display: "flex", justifyContent: "center" }} >
                        <img src={Space} alt='pic' style={{ maxWidth: "100%", maxHeight:"100%", overflow: "hidden", marginBottom: "20px" }} height={125} />
                    </div> 
                    
                    <div className={picClicked ? 'likeBtnContainer-hidden' : 'likeBtnContainer'}>
                        <button 
                            className='likeBtn' 
                            type='button' 
                            onClick={() => updateLike(post._id, index)}
                            disabled={likedPosts[post._id]} // 可选:点赞后禁用按钮
                        >
                            Like {likedPosts[post._id] ? likes[index] : post.likeCount}
                        </button>
                    </div>
                    <div className='deleteBtnContainer'>
                        <button className='deleteBtn' type='button' onClick={() => deletePost(post._id)}>Delete</button>
                    </div>
                </div>
            )}
        </>
    )
}

export default ExperienceLikes

关键修改点说明

  • 替换全局liked状态:改用likedPosts对象存储每个帖子的点赞状态,实现单帖独立控制,避免全局状态影响所有帖子。
  • 正确初始化与同步点赞数组:初始点赞数组从帖子列表中读取真实数据,通过useEffect监听列表变化,保证点赞数组与后端数据同步。
  • 修复帖子列表更新逻辑:更新列表时复制原帖子对象并修改点赞数,而非替换为ID字符串,保证列表数据的完整性。
  • 安全更新点赞数组:修改点赞数组时先复制原数组,再更新对应索引的值,避免直接修改原数组导致的状态更新异常。

内容的提问来源于stack exchange,提问作者Proper_poe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 06:55:20