如何利用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
相关产品推荐
相关产品推荐

