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

如何在localStorage持久化所有点赞数据集,实现点赞切换效果

解决页面刷新后重复点赞问题的修改方案

核心问题分析

当前代码的关键缺陷是:

  • 仅用单个localStorage键存储单次点赞/取消请求的返回值,无法追踪所有已点赞的照片ID集合
  • 组件初始化时未从localStorage恢复之前的点赞状态
  • 直接修改原数据数组和状态对象,违反React不可变状态更新原则
  • 点赞数显示依赖localStorage的孤立值,逻辑混乱

完整修改方案

1. 初始化时恢复点赞状态

将点赞状态与localStorage绑定,组件加载时自动读取历史点赞记录:

// 从localStorage读取已点赞照片集合,初始化组件状态
const [userLikedPhotos, setUserLikedPhotos] = useState(() => {
  const savedLikes = localStorage.getItem('userLikedPhotos');
  return savedLikes ? JSON.parse(savedLikes) : {};
});
// 将gridData转为组件状态,避免直接修改原数据
const [photosData, setPhotosData] = useState(gridData);

2. 修正点赞/取消逻辑(遵循不可变原则)

更新状态时创建新对象/数组,同时同步更新localStorage:

const handleLikesBasedOnUserId = (likedPhotoUserId, userName) => {
  setUserLikedPhotos(prevState => {
    // 创建新的点赞状态对象
    const newLikedState = {...prevState};
    // 创建新的照片数据数组
    const newPhotos = [...photosData];
    const targetPhoto = newPhotos.find(photo => photo.UserID === likedPhotoUserId);

    if (newLikedState[likedPhotoUserId]) {
      // 取消点赞:移除ID,点赞数减1
      delete newLikedState[likedPhotoUserId];
      targetPhoto.likes -= 1;
      handleDislike(likedPhotoUserId, userName);
    } else {
      // 点赞:添加ID,点赞数加1
      newLikedState[likedPhotoUserId] = true;
      targetPhoto.likes += 1;
      handleLike(likedPhotoUserId, userName);
    }

    // 持久化更新后的点赞集合
    localStorage.setItem('userLikedPhotos', JSON.stringify(newLikedState));
    // 更新照片数据状态
    setPhotosData(newPhotos);
    return newLikedState;
  });
};

3. 调整API请求逻辑(移除无效的localStorage存储)

去掉单个请求的localStorage存储,仅保留API交互,添加请求失败回滚:

const handleLike = (likedPhotoUserId, userName) => {
  const url = 'http://127.0.0.1:8000/api/like';
  const headers = {
    "Accept": 'application/json',
    "Authorization": `Bearer ${authToken}`
  };

  axios.post(url, {
    UserID: likedPhotoUserId,
    userName,
    liked: true // 补全原代码未定义的liked变量
  }, {headers})
  .then(resp => console.log(resp.data))
  .catch(err => {
    console.log(err);
    // API失败时回滚前端状态
    setUserLikedPhotos(prev => {
      const newState = {...prev};
      delete newState[likedPhotoUserId];
      localStorage.setItem('userLikedPhotos', JSON.stringify(newState));
      const newPhotos = [...photosData];
      newPhotos.find(p => p.UserID === likedPhotoUserId).likes--;
      setPhotosData(newPhotos);
      return newState;
    });
  });
};

const handleDislike = (likedPhotoUserId, userName) => {
  const url = 'http://127.0.0.1:8000/api/dislike';
  const headers = {
    "Accept": 'application/json',
    "Authorization": `Bearer ${authToken}`
  };

  axios.post(url, {
    UserID: likedPhotoUserId,
    userName,
    disliked: true // 补全原代码未定义的disliked变量
  }, {headers})
  .then(resp => console.log(resp.data))
  .catch(err => {
    console.log(err);
    // API失败时回滚前端状态
    setUserLikedPhotos(prev => {
      const newState = {...prev};
      newState[likedPhotoUserId] = true;
      localStorage.setItem('userLikedPhotos', JSON.stringify(newState));
      const newPhotos = [...photosData];
      newPhotos.find(p => p.UserID === likedPhotoUserId).likes++;
      setPhotosData(newPhotos);
      return newState;
    });
  });
};

4. 修正渲染逻辑(实时显示正确状态)

根据当前点赞状态动态调整按钮样式和文本,直接显示照片数据中的点赞数:

return (
  <>
    {photosData.map((photo, index) => (
      <div key={index}>
        <span className="likesAmt">❤️ {photo.likes}</span>
        <Button 
          variant={userLikedPhotos[photo.UserID] ? "secondary" : "success"}
          onClick={() => handleLikesBasedOnUserId(photo.UserID, photo.name)}
        >
          {userLikedPhotos[photo.UserID] ? "Unlike" : "Like"}
        </Button>
        <br/>
        <span className="name">
          {photo.name} 
          {localStorage.getItem('UserID') === photo.UserID ? <h6 className="you">(You)</h6> : null}
        </span>
      </div>
    ))}
  </>
);

修改后效果验证

  1. 点击点赞:点赞数+1,按钮变为"Unlike",localStorage记录该照片ID
  2. 刷新页面:组件自动读取localStorage,按钮保持"Unlike"状态
  3. 再次点击:点赞数-1,按钮变回"Like",localStorage移除该照片ID

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 01:25:24