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

React中实现关注状态切换按钮文本及刷新后状态保持

解决React关注/取消关注按钮刷新后状态不保持问题

核心问题出在组件刷新时,useState的初始状态没有同步localStorage中已更新的followers数据,导致按钮判断逻辑基于旧的状态渲染文本。下面是具体的修复方案:


1. 修正状态初始化逻辑

组件挂载时,优先从localStorage读取目标用户的followers数据,而非仅依赖API返回的初始值:

import { useState, useEffect } from 'react';
// 若需从JWT解析user_id,可引入jwt-decode(自行安装)
// import jwtDecode from 'jwt-decode';

const UserProfile = () => {
  // 获取当前登录用户ID
  const token = localStorage.getItem('jwt');
  const currentUserId = token ? JSON.parse(atob(token.split('.')[1])).user_id : null; // 手动解析JWT,或用jwt-decode
  const [profile, setProfile] = useState(null);

  useEffect(() => {
    const fetchProfile = async () => {
      // 调用API获取目标用户基础信息
      const res = await fetch(`/api/user/${targetUserId}`); // 替换为你的API地址
      const fetchedProfile = await res.json();

      // 从localStorage读取已保存的followers(用目标用户ID做key,避免多用户冲突)
      const savedFollowers = localStorage.getItem(`followers_${fetchedProfile.user_id}`);
      
      if (savedFollowers) {
        // 用localStorage的最新followers覆盖API返回值
        setProfile({ ...fetchedProfile, followers: JSON.parse(savedFollowers) });
      } else {
        // 首次加载时,把API返回的followers存入localStorage
        setProfile(fetchedProfile);
        localStorage.setItem(`followers_${fetchedProfile.user_id}`, JSON.stringify(fetchedProfile.followers));
      }
    };

    fetchProfile();
  }, [targetUserId]); // targetUserId需根据你的组件逻辑传入

2. 优化关注切换逻辑

确保每次切换状态时,同步更新state和localStorage,且基于当前状态判断按钮文本:

const handleFollowToggle = async () => {
  if (!profile || !currentUserId) return;

  const isFollowing = profile.followers.includes(currentUserId);
  let updatedFollowers;

  try {
    if (isFollowing) {
      // 取消关注:从followers移除当前用户ID
      updatedFollowers = profile.followers.filter(id => id !== currentUserId);
      await fetch(`/api/user/${profile.user_id}/unfollow`, { method: 'POST' });
    } else {
      // 关注:添加当前用户ID到followers
      updatedFollowers = [...profile.followers, currentUserId];
      await fetch(`/api/user/${profile.user_id}/follow`, { method: 'POST' });
    }

    // 更新组件状态
    setProfile(prev => ({ ...prev, followers: updatedFollowers }));
    // 同步更新localStorage
    localStorage.setItem(`followers_${profile.user_id}`, JSON.stringify(updatedFollowers));
  } catch (err) {
    // API调用失败时,可添加错误提示或回滚状态
    console.error('关注操作失败:', err);
  }
};

3. 动态渲染按钮文本

用一个按钮替代两个独立按钮,根据当前followers状态动态切换文本:

{profile && currentUserId && (
  <button onClick={handleFollowToggle} className="follow-btn">
    {profile.followers.includes(currentUserId) ? '取消关注' : '关注'}
  </button>
)}

关键注意事项

  • 存储followers时,必须用目标用户ID作为localStorage的key,避免多个用户的关注状态互相覆盖。
  • 若API调用失败,需处理错误回滚,防止localStorage与后端数据不一致。
  • 若JWT存储在localStorage,解析user_id时要注意安全性(避免XSS风险,可考虑将敏感数据存在HttpOnly Cookie)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 23:42:28