如何在React中使用AWS Amplify Auth API,避免页面刷新与跳转?
解决AWS Amplify谷歌登录与登出的页面行为问题
原始代码
export default function Home() { const [user, setUser] = useState(""); useEffect(() => { Auth.currentAuthenticatedUser().then((user) => { setUser(user.username); }); Hub.listen("auth", (data) => { switch (data.payload.event) { case "signIn": return setUser(data.payload.data.username); case "signOut": return setUser(""); } }); }, [setUser]); const handleGoogleLogin = () => { Auth.federatedSignIn({ provider: CognitoHostedUIIdentityProvider.Google, }); }; const handleSignOut = () => { Auth.signOut({ global: true, }).then(() => {}); }; return ( <> {!user && <button onClick={handleGoogleLogin}>Google</button>} {user && ( <button onClick={handleSignOut}>LogOut</button> )} <h1>Hello {user}, this is my app</h1> </> ); }
当前存在的问题
- 调用
Auth.federatedSignIn时,谷歌登录表单直接在当前标签页打开,打断应用正常流程 - 调用
Auth.signOut({ global: true })会强制刷新页面,无法通过Hub监听事件优雅更新用户状态
解决方案
1. 让谷歌登录在新标签页打开,完全依赖Hub触发状态更新
修改登录逻辑,构造登录URL后在新标签页打开,用户完成登录后Hub会自动捕获signIn事件更新状态。注意redirectUri需提前在Cognito用户池的回调地址中配置。
const handleGoogleLogin = () => { const signInUrl = Auth.federatedSignIn({ provider: CognitoHostedUIIdentityProvider.Google, redirectUri: window.location.origin + '/', // 替换为你的应用回调地址 }); // 在新标签页打开登录窗口,指定尺寸提升体验 window.open(signInUrl, '_blank', 'width=500,height=600'); };
2. 取消登出时的页面刷新,靠Hub监听更新状态
global: true参数会触发全局登出并强制刷新所有关联页面,移除该参数后,Auth.signOut()仅清除本地会话,Hub会捕获signOut事件自动更新用户状态。
const handleSignOut = async () => { try { await Auth.signOut(); // 无需手动调用setUser,Hub会自动处理状态更新 } catch (err) { console.error('登出失败:', err); } };
优化后的完整组件
import { useState, useEffect } from 'react'; import { Auth, Hub } from 'aws-amplify'; import { CognitoHostedUIIdentityProvider } from '@aws-amplify/auth'; export default function Home() { const [user, setUser] = useState(""); useEffect(() => { // 初始化时获取当前已登录用户 const fetchCurrentUser = async () => { try { const currentUser = await Auth.currentAuthenticatedUser(); setUser(currentUser.username); } catch (err) { // 用户未登录时忽略错误 console.log('用户未登录'); } }; fetchCurrentUser(); // 监听Auth事件 const authListener = Hub.listen("auth", (data) => { switch (data.payload.event) { case "signIn": setUser(data.payload.data.username); break; case "signOut": setUser(""); break; } }); // 组件卸载时清理监听 return () => authListener(); }, []); // 优化依赖项,setUser是稳定函数无需放入 const handleGoogleLogin = () => { const signInUrl = Auth.federatedSignIn({ provider: CognitoHostedUIIdentityProvider.Google, redirectUri: window.location.origin + '/', }); window.open(signInUrl, '_blank', 'width=500,height=600'); }; const handleSignOut = async () => { try { await Auth.signOut(); } catch (err) { console.error('登出失败:', err); } }; return ( <> {!user && <button onClick={handleGoogleLogin}>Google登录</button>} {user && <button onClick={handleSignOut}>登出</button>} <h1>Hello {user || '访客'}, this is my app</h1> </> ); }
内容的提问来源于stack exchange,提问作者Vitor Figueredo Marques
相关产品推荐
相关产品推荐

