React页面刷新时如何执行Cognito getSession异步函数获取数据后再渲染?
解决方案
第一步:封装异步getSession方法
首先把Cognito回调形式的getSession封装为Promise版本,方便后续异步逻辑调用:
export const getCurrentSession = async (): Promise<CognitoUserSession | null> => { const currentUser = userPool.getCurrentUser(); if (!currentUser) return null; return new Promise((resolve, reject) => { currentUser.getSession((err, session) => { if (err) return reject(err); resolve(session.isValid() ? session : null); }) }) }
第二步:选择适配你技术栈的实现方式
以下两种方案都可以实现「鉴权完成后再渲染页面内容」的需求:
方案1:根组件全局初始化(最常用)
在应用根组件(一般为App.tsx)加全局鉴权loading,等校验完成再渲染路由内容:
import { useEffect, useState } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import { updateToken } from './你的auth切片路径'; import { getCurrentSession } from './cognito工具文件路径'; function App() { const [authInitialized, setAuthInitialized] = useState(false); const dispatch = useDispatch(); const token = useSelector(state => state.auth.token); useEffect(() => { const initAuth = async () => { try { const session = await getCurrentSession(); if (session) { const accessToken = session.getAccessToken().getJwtToken(); localStorage.setItem("user", JSON.stringify(accessToken)); dispatch(updateToken(accessToken)); } } catch (err) { // token无效/过期时清空本地存储和redux状态 localStorage.removeItem("user"); dispatch(updateToken(null)); } finally { setAuthInitialized(true); } }; initAuth(); }, [dispatch]); // 鉴权未完成时只渲染loading,不渲染任何路由内容 if (!authInitialized) return <div>加载中...</div>; return ( {/* 你的路由配置 */} <Routes> <Route path="/login" element={<登录页组件 />} /> <Route path="/私有路径" element={ <PrivateRoute> <私有页面组件 /> </PrivateRoute> } /> </Routes> ) }
方案2:PrivateRoute组件内处理
如果不想在根组件加逻辑,也可以直接在私有路由组件内统一处理鉴权校验:
import { Navigate } from 'react-router-dom'; import { useEffect, useState } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import { getCurrentSession } from './cognito工具文件路径'; import { updateToken } from './你的auth切片路径'; const PrivateRoute = ({ children }) => { const [checkingAuth, setCheckingAuth] = useState(true); const dispatch = useDispatch(); const token = useSelector(state => state.auth.token); useEffect(() => { const checkValid = async () => { // redux无token时才调用Cognito接口校验本地存储的token有效性 if (!token) { try { const session = await getCurrentSession(); if (session) { const accessToken = session.getAccessToken().getJwtToken(); dispatch(updateToken(accessToken)); } } catch (err) { localStorage.removeItem("user"); } } setCheckingAuth(false); }; checkValid(); }, [token, dispatch]); if (checkingAuth) return <div>鉴权中...</div>; return token ? children : <Navigate to="/login" replace />; }
注意事项
- 不要尝试用同步逻辑阻塞组件渲染,React生态下没有稳定可靠的同步阻塞方案,加loading状态是成本最低、兼容性最好的实现方式
- 如果你的项目用了Redux Toolkit Query等工具,也可以把鉴权逻辑放在全局middleware中处理,效果和根组件初始化一致
内容的提问来源于stack exchange,提问作者jayjay
相关产品推荐
相关产品推荐

