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
相关产品推荐
相关产品推荐

