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

如何利用localStorage实现用户单次点赞限制及刷新后状态保持

解决页面刷新后点赞状态不持久的问题

当前实现的点赞功能存在刷新后状态丢失的问题:

  • 错误流程:点赞→点赞数+1→刷新页面→再次点赞→点赞数继续+1(可重复操作)
  • 预期流程:点赞→点赞数+1→刷新页面→再次点击→点赞数-1(可切换点赞状态)

已知需要通过localStorage存储已点赞的UserID,但映射存储的实现存在问题,以下是修正方案:

核心问题分析

你的代码中存在两个关键问题:

  • 初始化时没有从localStorage读取已有的点赞记录,导致刷新后userLikedPhotos为空
  • 每次点赞时都创建新的空对象mapOfLikes,覆盖了之前存储的所有点赞记录,没有做到增量更新

解决方案

步骤1:初始化时从localStorage恢复点赞状态

在组件初始化时,读取localStorage中保存的点赞记录,赋值给userLikedPhotos。

步骤2:同步更新localStorage

每次修改点赞状态后,将最新的userLikedPhotos同步到localStorage,而不是创建新对象。

步骤3:正确修改gridData(不可变更新)

直接修改gridData中的对象不会触发组件重新渲染,需要创建新的数组副本。

修改后的完整代码

// 初始化state时从localStorage读取已保存的点赞记录
const [userLikedPhotos, setUserLikedPhotos] = useState(() => {
  const savedLikes = localStorage.getItem('userLikedPhotos');
  return savedLikes ? JSON.parse(savedLikes) : {};
});

const [gridData, setGridData] = 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 => {
            console.log(resp.data);
            setGridData(resp.data);
        }).catch(err => {
        console.log(err);
    });
}, []);


const handleLikesBasedOnUserId = (likedPhotoUserId, userName) => {
    // 创建状态副本,避免直接修改原state
    const updatedLikes = {...userLikedPhotos};
    const updatedGridData = [...gridData];

    if(updatedLikes[likedPhotoUserId]) {
        // 取消点赞逻辑
        delete updatedLikes[likedPhotoUserId];
        // 找到对应图片并更新点赞数(不可变更新)
        const photoIndex = updatedGridData.findIndex(photo => photo.UserID === likedPhotoUserId);
        if(photoIndex !== -1) {
            updatedGridData[photoIndex] = {...updatedGridData[photoIndex], likes: updatedGridData[photoIndex].likes - 1};
        }
        handleDislike(likedPhotoUserId, userName);

    } else {
        // 点赞逻辑
        updatedLikes[likedPhotoUserId] = true;
        const photoIndex = updatedGridData.findIndex(photo => photo.UserID === likedPhotoUserId);
        if(photoIndex !== -1) {
            updatedGridData[photoIndex] = {...updatedGridData[photoIndex], likes: updatedGridData[photoIndex].likes + 1};
        }
        handleLike(likedPhotoUserId, userName);
    }

    // 更新组件状态
    setUserLikedPhotos(updatedLikes);
    setGridData(updatedGridData);
    // 同步最新点赞状态到localStorage
    localStorage.setItem('userLikedPhotos', JSON.stringify(updatedLikes));
};

return(
  <>
     {gridData.map((photos, index) => (
        <div key={index}>
            <span className="likesAmt">❤️ {photos.likes}</span><br/>
            {/* 根据点赞状态动态切换按钮样式和文字 */}
            <Button 
                variant={userLikedPhotos[photos.UserID] ? "danger" : "success"}
                onClick={() => handleLikesBasedOnUserId(photos.UserID, photos.name)}
            >
                {userLikedPhotos[photos.UserID] ? "Dislike" : "Like"}
            </Button><br/>
            <span className="name">
                {photos.name} 
                {localStorage.getItem('UserID') === photos.UserID ? <h6 className="you">(You)</h6> : null}
            </span>
        </div>
     ))}
  </>
);

关键修改说明

  • 状态持久化初始化:通过useState的函数初始化器,从localStorage读取已保存的点赞记录,确保刷新页面后状态不会丢失
  • 不可变更新:修改userLikedPhotos和gridData时都创建副本,避免直接修改原state,保证组件能正确触发重新渲染
  • 同步localStorage:每次点赞/取消点赞操作后,将最新的点赞状态存入localStorage,覆盖旧数据,保证本地存储与组件状态一致
  • 用户体验优化:根据当前点赞状态动态切换按钮的样式和文字,让用户直观看到当前状态

内容的提问来源于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 12:45:41