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

React+TypeScript应用Facebook登录SDK页面刷新自动登出,求完整教程

React + TypeScript 持久化Facebook登录状态完整实现指南

核心问题分析

页面刷新或路由切换后自动登出,本质是页面重新加载后Facebook SDK未主动检查已有的登录状态,且未将登录信息持久化存储,导致组件无法恢复之前的登录状态。以下是完整的分步实现方案:


1. 全局加载Facebook SDK

首先确保在React应用中正确加载Facebook SDK,且每次页面加载时都完成初始化:

// src/utils/facebookSdk.ts
declare global {
  interface Window {
    fbAsyncInit: () => void;
    FB: any;
  }
}

export const loadFacebookSDK = (appId: string) => {
  if (window.FB) return;

  window.fbAsyncInit = () => {
    window.FB.init({
      appId: appId,
      cookie: true, // 启用cookie,让SDK可以在页面刷新后保留会话
      xfbml: true,
      version: 'v18.0' // 替换为你使用的SDK版本
    });
  };

  // 注入SDK脚本
  const script = document.createElement('script');
  script.src = `https://connect.facebook.net/en_US/sdk.js`;
  script.async = true;
  script.defer = true;
  document.body.appendChild(script);
};

2. 完整登录状态管理组件

创建封装Facebook登录逻辑的组件,集成状态检查、登录、登出及持久化:

// src/components/FacebookLogin.tsx
import { useEffect, useState } from 'react';
import { loadFacebookSDK } from '../utils/facebookSdk';

interface FacebookUser {
  id: string;
  name: string;
  email: string;
  picture: { data: { url: string } };
}

const FacebookLogin = () => {
  const [user, setUser] = useState<FacebookUser | null>(null);
  const [isLoading, setIsLoading] = useState(true);
  const FB_APP_ID = '你的Facebook App ID'; // 替换为你的实际App ID

  // 初始化SDK并检查登录状态
  useEffect(() => {
    loadFacebookSDK(FB_APP_ID);

    const checkLoginStatus = () => {
      if (!window.FB) {
        setTimeout(checkLoginStatus, 500);
        return;
      }

      // 先读取本地存储的登录信息
      const savedUser = localStorage.getItem('facebook_user');
      const savedToken = localStorage.getItem('facebook_access_token');

      if (savedUser && savedToken) {
        // 先恢复本地状态,再验证token有效性
        setUser(JSON.parse(savedUser));
        window.FB.getLoginStatus((response: any) => {
          if (response.status !== 'connected') {
            // token失效,清除本地存储
            localStorage.removeItem('facebook_user');
            localStorage.removeItem('facebook_access_token');
            setUser(null);
          }
          setIsLoading(false);
        });
      } else {
        // 本地无存储,直接调用SDK检查当前登录状态
        window.FB.getLoginStatus((response: any) => {
          if (response.status === 'connected') {
            fetchUserInfo(response.authResponse.accessToken);
          }
          setIsLoading(false);
        });
      }
    };

    checkLoginStatus();
  }, []);

  // 获取用户公开信息
  const fetchUserInfo = (accessToken: string) => {
    window.FB.api('/me', {
      fields: 'id,name,email,picture',
      access_token: accessToken
    }, (response: any) => {
      if (response.id) {
        setUser(response);
        // 持久化到localStorage
        localStorage.setItem('facebook_user', JSON.stringify(response));
        localStorage.setItem('facebook_access_token', accessToken);
      }
    });
  };

  // 触发登录
  const handleLogin = () => {
    window.FB.login((response: any) => {
      if (response.status === 'connected') {
        fetchUserInfo(response.authResponse.accessToken);
      }
    }, { scope: 'public_profile,email' });
  };

  // 触发登出
  const handleLogout = () => {
    window.FB.logout(() => {
      setUser(null);
      localStorage.removeItem('facebook_user');
      localStorage.removeItem('facebook_access_token');
    });
  };

  if (isLoading) return <div>加载中...</div>;

  return (
    <div>
      {user ? (
        <div className="flex items-center gap-3">
          <img src={user.picture.data.url} alt={user.name} className="w-12 h-12 rounded-full" />
          <span>欢迎, {user.name}</span>
          <button onClick={handleLogout} className="ml-4 px-4 py-2 bg-gray-200 rounded">
            登出Facebook
          </button>
        </div>
      ) : (
        <button onClick={handleLogin} className="px-6 py-2 bg-blue-600 text-white rounded">
          使用Facebook登录
        </button>
      )}
    </div>
  );
};

export default FacebookLogin;

3. 关键注意事项

  • cookie: true:初始化SDK时必须启用cookie,否则SDK无法在页面刷新后识别用户会话。
  • 双重状态验证:先从localStorage恢复状态,再调用FB.getLoginStatus验证token有效性,避免本地存储的信息过期失效。
  • token有效期:Facebook用户access token默认有效期为60天,若需长期登录,可在后端实现refresh token刷新逻辑(前端仅存储refresh token,由后端调用Facebook接口更新access token)。
  • TypeScript类型兼容:通过declare global扩展Window接口,解决FB全局变量的类型报错问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 14:46:21