如何阻止React Router loader函数执行未认证的无效请求?
解决React Router 6.4.2受保护路由loader提前执行的问题
问题背景
使用createBrowserRouter配置路由时,主路由/设置了loader用于获取默认数据,且该路由被RequireAuth组件保护,未认证用户访问时会重定向到/auth。但实际场景中,未认证用户访问/时,loader会先执行再触发重定向,导致请求因缺少授权令牌失败。
优雅解决方案
方案1:在loader中前置认证检查(推荐)
利用React Router的loader可抛出重定向的特性,在getDefaultData最开始用Amplify底层API直接检查认证状态,未认证时直接抛出重定向,阻止后续请求逻辑执行:
import { redirect } from "react-router-dom"; import { Auth } from "aws-amplify"; export const getDefaultData = async () => { try { // 直接通过Amplify Auth API检查当前用户状态 await Auth.currentAuthenticatedUser(); // 认证通过,执行数据请求 store.dispatch( getData({ someVariables, }) ); } catch (err) { // 未认证时抛出重定向,终止loader执行 return redirect("/auth"); } };
同时保留RequireAuth组件的守卫逻辑作为双重保障:
export const RequireAuth = ({ children }: Props) => { const location = useLocation(); const { route } = useAuthenticator((context) => [context.route]); if (route !== 'authenticated') { return <Navigate to="/auth" state={{ from: location }} replace />; } return <>{children}</>; };
方案2:父路由添加认证loader
将认证逻辑抽为独立loader挂载到父路由,父路由loader会优先于子路由执行,未认证时直接重定向,从根源阻止子路由loader运行:
import { redirect } from "react-router-dom"; import { Auth } from "aws-amplify"; // 父路由专属认证loader const authGuardLoader = async () => { try { await Auth.currentAuthenticatedUser(); return null; // 认证通过,放行子路由 } catch (err) { return redirect("/auth"); } }; // 更新路由配置 const router = createBrowserRouter([ { element: ( <RequireAuth> <AppLayout /> </RequireAuth> ), loader: authGuardLoader, // 父路由前置认证 children: [ { path: '/', loader: getDefaultData, element: <MainPage />, }, ], }, { path: '/auth', element: <Authenticator /> }, { path: '*', element: <NotFoundPage /> }, ]);
补充说明
- 不推荐在请求阶段才做认证检查:这种方式无法阻止loader执行到请求步骤,仍会触发无效请求。
shouldRevalidate不适用:该API用于控制路由重新验证的时机(如导航回退时是否重新执行loader),无法阻止首次访问时的loader执行。
内容的提问来源于stack exchange,提问作者MadaShindeInai
相关产品推荐
相关产品推荐

