如何在其他组件登录后,无需刷新同步更新AppBar的用户信息
解决AppBar与Profile组件登录状态不同步问题
问题原因:AppBar组件的useEffect仅在组件挂载时执行一次Auth.currentAuthenticatedUser(),登录完成后不会自动重新触发,导致状态无法同步;而Profile组件使用的Authenticator内部已监听登录状态变化,因此能实时更新用户信息。
以下是几种可行的解决方案:
方案一:使用Amplify官方的useAuthenticator钩子(最简方案)
Amplify的@aws-amplify/ui-react包提供了useAuthenticator钩子,可直接获取全局同步的用户状态,无需手动监听事件或管理状态:
import { useAuthenticator } from '@aws-amplify/ui-react'; function AppBar() { const { user } = useAuthenticator(); return <div>AppBar: {user?.username || '未登录'}</div>; } function Profile() { return <Authenticator> {({ user, signOut }) => ( <> <div>Profile: { user.username }</div> <button onClick={signOut}>Sign Out</button> </> )} </Authenticator> } function App() { return ( <> <AppBar /> <Profile /> </> ); }
方案二:监听Auth事件手动同步状态
通过Amplify Auth提供的事件监听机制,在AppBar中监听signIn和signOut事件,触发用户信息重新获取:
import { useState, useEffect } from 'react'; import { Auth } from 'aws-amplify'; function AppBar() { const [user, setUser] = useState<string | null>(null); // 封装获取用户信息的方法 const fetchCurrentUser = async () => { try { const authUser = await Auth.currentAuthenticatedUser(); setUser(authUser.username); } catch (err) { // 用户未登录时重置状态 setUser(null); } }; useEffect(() => { // 初始加载用户信息 fetchCurrentUser(); // 监听登录事件,触发状态更新 const signInListener = Auth.listen('signIn', fetchCurrentUser); // 监听登出事件,触发状态更新 const signOutListener = Auth.listen('signOut', fetchCurrentUser); // 组件卸载时清除监听 return () => { signInListener(); signOutListener(); }; }, []); return <div>AppBar: {user || '未登录'}</div>; } // Profile和App组件保持不变
方案三:使用React Context共享全局用户状态
通过创建Auth上下文,将用户状态提升到全局,让所有需要的组件共享同步状态:
1. 创建AuthContext
import { createContext, useContext, useState, useEffect } from 'react'; import { Auth } from 'aws-amplify'; const AuthContext = createContext<{ user: any | null }>({ user: null }); export function AuthProvider({ children }) { const [user, setUser] = useState<any | null>(null); const fetchUser = async () => { try { const authUser = await Auth.currentAuthenticatedUser(); setUser(authUser); } catch (err) { setUser(null); } }; useEffect(() => { fetchUser(); const signInListener = Auth.listen('signIn', fetchUser); const signOutListener = Auth.listen('signOut', fetchUser); return () => { signInListener(); signOutListener(); }; }, []); return ( <AuthContext.Provider value={{ user }}> {children} </AuthContext.Provider> ); } // 自定义钩子简化上下文调用 export function useAuth() { return useContext(AuthContext); }
2. 在App组件中包裹Provider
import { AuthProvider } from './AuthContext'; function App() { return ( <AuthProvider> <AppBar /> <Profile /> </AuthProvider> ); }
3. 修改AppBar和Profile组件使用Context
// AppBar组件 import { useAuth } from './AuthContext'; function AppBar() { const { user } = useAuth(); return <div>AppBar: {user?.username || '未登录'}</div>; } // Profile组件(可选,也可继续使用Authenticator) import { useAuth } from './AuthContext'; import { useAuthenticator } from '@aws-amplify/ui-react'; function Profile() { const { user } = useAuth(); const { signOut } = useAuthenticator(); if (!user) { return <Authenticator />; } return ( <> <div>Profile: {user.username}</div> <button onClick={signOut}>Sign Out</button> </> ); }
内容的提问来源于stack exchange,提问作者eugenekr
相关产品推荐
相关产品推荐

