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

如何修复React中类似Instagram点赞功能的分支判断异常

修复Instagram风格点赞/取消点赞功能的分支判断问题

问题核心

当前代码存在三个关键问题导致点击按钮总是进入点赞分支:

  • userLikedPhotos 初始为空对象,未从 gridData 同步初始点赞状态,导致判断条件永远为假
  • 使用用户ID作为 userLikedPhotos 的键不合理,同一个用户的多张照片可独立点赞,应使用照片ID作为唯一标识
  • 直接修改原状态对象/数组(如delete userLikedPhotos[likedPhotoUserId]、修改gridData元素的likes)违反React状态不可变原则,会导致状态更新不生效或异常

修复步骤

  1. 初始化同步点赞状态:获取gridData后,将每张照片的点赞状态同步到userLikedPhotos,用照片ID作为键
  2. 修正判断逻辑:根据照片ID判断当前是否已点赞,而非用户ID
  3. 遵循状态不可变原则:修改状态时创建新的对象/数组副本,不直接修改原状态

修改后的完整代码

const Grid = () => {
  const authToken = localStorage.getItem('token');

  const [gridData, setGridData] = useState([]);
  const [userLikedPhotos, setUserLikedPhotos] = useState({});

  useEffect(() => {
    const headers = {
      "Accept": 'application/json',
      "Authorization": `Bearer ${authToken}`
    };

    axios.get('http://127.0.0.1:8000/api/get-user-uploads-data', {headers})
      .then(resp => {
        const data = resp.data;
        setGridData(data);
        // 初始化同步已点赞状态,用photo_id作为唯一标识键
        const initialLikedState = {};
        data.forEach(photo => {
          if (photo.is_liked) {
            initialLikedState[photo.photo_id] = true;
          }
        });
        setUserLikedPhotos(initialLikedState);
      }).catch(err => {
        console.log(err);
      });
  }, []);

  const handleLikesBasedOnUserId = (likedPhotoUserId, userName, likedPhotoId) => {
    // 基于照片ID判断当前是否已点赞
    if (userLikedPhotos[likedPhotoId]) {
      // 取消点赞逻辑
      handleDislike(likedPhotoUserId, userName, likedPhotoId);
      // 创建新状态副本,删除对应照片的点赞记录
      const newUserLikedPhotos = {...userLikedPhotos};
      delete newUserLikedPhotos[likedPhotoId];
      setUserLikedPhotos(newUserLikedPhotos);
      // 更新gridData,同步点赞数和状态
      setGridData(prevData => prevData.map(photo => {
        if (photo.photo_id === likedPhotoId) {
          return {...photo, likes: photo.likes - 1, is_liked: false};
        }
        return photo;
      }));
      console.log("Disliked");
    } else {
      // 点赞逻辑
      handleLike(likedPhotoUserId, userName, likedPhotoId);
      // 创建新状态副本,添加对应照片的点赞记录
      setUserLikedPhotos(prev => ({...prev, [likedPhotoId]: true}));
      // 更新gridData,同步点赞数和状态
      setGridData(prevData => prevData.map(photo => {
        if (photo.photo_id === likedPhotoId) {
          return {...photo, likes: photo.likes + 1, is_liked: true};
        }
        return photo;
      }));
      console.log("Liked");
    }
  };

  return (
    <>
      <div className="img-container">
        {gridData.map((photo, index) => (
          <div key={photo.photo_id} className="userDetails">
            <span className="likesAmt">❤️ {photo.likes}</span>
            <Button 
              variant={photo.is_liked ? 'danger' : 'success'} 
              onClick={() => handleLikesBasedOnUserId(photo.UserID, photo.name, photo.photo_id)}
            >
              {photo.is_liked ? 'Dislike' : 'Like'}
            </Button>
          </div>
        ))}
      </div>                
    </>
  )
}

export default Grid;

关键修改说明

  • 在useEffect中初始化userLikedPhotos:遍历gridData,将已点赞的照片ID作为键存入状态,确保初始判断准确
  • 用photo_id代替用户ID作为userLikedPhotos的键,解决同一用户多张照片的独立点赞问题
  • 修改状态时均创建新的对象/数组副本(展开运算符、map方法),遵循React状态不可变原则,确保状态更新触发组件重新渲染
  • 更新gridData时同步修改is_liked和likes字段,保证UI显示与状态实时一致

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 12:01:06