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

如何在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>
    </>
  );
}

当前存在的问题

  1. 调用Auth.federatedSignIn时,谷歌登录表单直接在当前标签页打开,打断应用正常流程
  2. 调用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 16:20:21