- 前端
- UI组件
【免费下载链接】react-admin
A frontend Framework for single-page applications on top of REST/GraphQL APIs, using TypeScript, React and Material Design
useAuthState是 react-admin 中用于查询当前用户认证状态的 Hook,它在组件挂载时调用authProvider.checkAuth(),并返回包含isPending、authenticated、error的状态对象。本指南讲解该 Hook 的返回值语义、与useAuthenticated()的核心差异、完整参数用法,并结合packages/ra-core/src/auth/useAuthState.ts源码与测试剖析其底层实现,帮助你为自定义页面编写认证感知的渲染逻辑。
useAuthState 是什么
在 react-admin 应用中,authProvider.checkAuth()负责校验当前用户是否已通过身份验证。如果你希望自行决定根据认证结果渲染什么内容(而不是被强制跳转到登录页),就可以使用useAuthState这个 Hook。
它挂载时调用authProvider.checkAuth()方法并返回一个状态对象,完整状态如下:
| 状态 | 返回值 |
|---|---|
| 加载中(等待 checkAuth 响应) | { isPending: true } |
| 已认证 | { isPending: false, authenticated: true } |
| 未认证 | { isPending: false, authenticated: false } |
| 认证检查出错 | { isPending: false, error: Error } |
从源码可以看到,最终返回结果是 react-query 的QueryObserverResult与authenticated字段的组合,其中authenticated的定义是:queryResult.error ? false : queryResult.data(见 useAuthState.ts)。也就是说,只要checkAuth()抛错,authenticated就为false,同时error字段携带错误详情。
与 useAuthenticated() 的核心区别
官方文档特别强调:与useAuthenticated()不同,useAuthState在用户未认证时不会重定向到登录页。
useAuthenticated()默认在认证失败时调用authProvider.logout()并重定向到/login,适合"强制拦截匿名访问"的场景;react-admin 核心组件(如<EditBase>)正是靠它来禁止未认证用户访问。useAuthState()则纯粹"报告状态",把渲染决策完全交给你。如果你想根据认证状态渲染不同内容(例如登录用户看到"个人中心"、匿名用户看到"请登录"提示),请使用useAuthState。
从源码看,useAuthenticated本质上是useAuthState的一层薄封装,只是把logoutOnFailure默认值设为true(见 useAuthenticated.ts),而useAuthState的logoutOnFailure默认为false。
基本用法
在需要区分认证状态的页面组件中解构isPending与authenticated即可:
import { useAuthState } from 'ra-core'; import { Loading } from './Loading'; const MyPage = () => { const { isPending, authenticated } = useAuthState(); if (isPending) { return <Loading />; } if (authenticated) { return <AuthenticatedContent />; } return <AnonymousContent />; };典型应用场景是自定义页面(CustomRoutes声明的路由默认对匿名用户开放,见 Authentication.md)。你可以用该 Hook 在同一页面内对登录/未登录用户呈现不同的 UI,而无需为每个用户组单独建页。
参数详解
useAuthState接受三个可选参数,源码签名如下(见 useAuthState.ts):
useAuthState<ErrorType = Error>( params?: any, // 传给 authProvider.checkAuth() 的参数 logoutOnFailure?: boolean, // 检查失败时是否登出,默认 false queryOptions?: UseAuthStateOptions<ErrorType> // 透传给 useQuery 的选项 )params:透传给 checkAuth 的上下文参数
任何你想传给authProvider.checkAuth()的对象。例如useAuthState({ foo: 'bar' })会调用authProvider.checkAuth({ foo: 'bar' })。它常被用来携带调用上下文(如来源页面),便于 authProvider 做精细化判断。注意signal(AbortSignal)也会被合并进这些参数一并传入(见 useAuthState.ts),用于请求取消。
logoutOnFailure:失败时是否登出
- 默认值:
false(useAuthState只报状态、不采取行动)。 - 设为
true时,若checkAuth()抛错,将调用authProvider.logout()并跳转到登录页(或错误对象redirectTo指定的地址),同时弹出ra.auth.auth_check_error通知。
该行为在 useAuthState.ts 的默认onError中实现:重定向优先级为error.redirectTo> 默认登录 URL;若错误对象的message为false则跳过通知。这正是useAuthenticated()继承的行为。
queryOptions:复用 react-query 能力
由于useAuthState底层基于@tanstack/react-query的useQuery(见 useAuthState.ts),除queryKey/queryFn外的其余选项都可以透传,包括onSuccess、onError、onSettled、enabled、retryDelay、staleTime等。例如可通过enabled: false延迟/关闭认证检查,或通过onSuccess在认证通过后触发埋点等副作用。
底层实现剖析
从 useAuthState.ts 源码可以梳理出完整调用链:
- queryKey 设计:查询键为
['auth', 'checkAuth', params],不同params会生成独立缓存条目,相同查询在应用内共享。 - checkAuth 调用:
queryFn内执行await authProvider.checkAuth({ ...params, signal });成功返回true,抛错则原样抛出(null错误会被规范化为Error实例)。 - 无 authProvider 的降级:react-admin 的 authProvider 是可选的。若未配置 authProvider,
useAuthState直接返回一个内置的静态结果{ authenticated: true, isPending: false, status: 'success' },即"默认视为已认证"(见 useAuthState.ts)。 - 副作用编排:
onSuccess/onError/onSettled通过useEvent包裹,并在useEffect中依据查询结果触发,且当queryOptions.enabled === false时全部跳过。 - 请求取消支持:
signal贯穿 checkAuth 调用,意味着 react-query 取消查询时会向 authProvider 传递中止信号。
测试用例印证
仓库配套测试 useAuthState.spec.tsx 验证了三个关键行为:
- 未提供 authProvider 时,一个 tick 后返回
AUTHENTICATED: true; - authProvider 的
checkAuthreject 后,返回AUTHENTICATED: false且不再显示 LOADING; - 通过
queryClient.cancelQueries({ queryKey: ['auth', 'checkAuth'] })取消查询时,authProvider 收到的signal会触发 abort 回调,证明取消机制真实生效。
这些测试同时说明了useAuthState必须运行在<CoreAdminContext>(或<Admin>)内,因为它依赖其提供的 authProvider 与 QueryClient。
配套组件与相关 Hook
<Authenticated>组件:useAuthenticated的组件版封装,适合因 Hooks 规则限制而无法调用 Hook 的场景(见 Authenticated.tsx)。它渲染children前会用useAuthenticated检查认证,isPending或isError时渲染loading(默认null)。useAuthenticated()Hook:见上文,等同于useAuthState(params, true, options),强制拦截匿名访问。useCheckAuth()底层 Hook:返回一个可手动调用的checkAuth(params, logoutOnFailure, redirectTo)回调,失败时负责登出、通知与抛错(见 useCheckAuth.ts)。useAuthState与其行为对比如下:
| 能力 | useAuthState | useAuthenticated | useCheckAuth |
|---|---|---|---|
| 自动在挂载时检查 | ✅ | ✅ | ❌(需手动调用) |
| 返回认证状态 | ✅ | 仅返回 isPending | ❌(Promise) |
| 失败默认登出重定向 | ❌(默认 false) | ✅(默认 true) | ✅(默认 true) |
| 按状态渲染不同内容 | ✅ 推荐 | 部分 | 需要自管状态 |
编写配套的 authProvider.checkAuth
useAuthState的行为完全取决于你实现的authProvider.checkAuth()。按 AuthProviderWriting.md 的约定:
- 用途:在访问需认证路由时检查用户是否已登录;
- resolve:表示通过校验(返回
void即可); - reject:抛出错误,react-admin 据此登出并重定向。默认跳
/login,可通过error.redirectTo自定义跳转地址;可通过error.message自定义通知文案(或设为false关闭通知),文案会被传入翻译层。
const authProvider = { async checkAuth() { if (!localStorage.getItem('auth')) { throw new Error(); // 触发登出并跳转 /login } }, // ... };结合本文源码分析可知,useAuthState成功/失败分支完全由该方法的 resolve/reject 驱动:resolve 后authenticated为true,reject 后为false且error携带错误对象。另外,被标记为允许匿名访问的路由不会调用checkAuth(见 AuthProviderWriting.md),因此这类页面上useAuthState的结果需要结合具体路由配置理解。
小结
useAuthState是 react-admin 认证体系中最灵活的"状态观察者":它把"是否认证"这一事实用{ isPending, authenticated, error }完整暴露给组件,且默认不做任何强制跳转。当你需要在同一页面为登录/匿名用户渲染差异化内容时,优先选择它;当需要强制保护某个自定义页面时,再考虑useAuthenticated()或<Authenticated>组件。深入理解其基于 react-query 的实现(查询缓存、signal取消、logoutOnFailure行为)有助于你在实际项目中正确使用并避免常见的状态误判。
- 前端
- UI组件
【免费下载链接】react-admin
A frontend Framework for single-page applications on top of REST/GraphQL APIs, using TypeScript, React and Material Design
相关推荐
react-admin 认证状态检测实战:useAuthState Hook 完整指南
react admin 认证状态检测实战:useAuthState Hook 完整指南 useAuthState 是 react admin 框架提供的认证状态
前端UI组件react-native-swiper条件渲染:根据不同状态显示不同轮播内容
react native swiper条件渲染:根据不同状态显示不同轮播内容 你是否遇到过这样的场景:在开发React Native应用时,需要根据用户登录状态
移动开发UI组件amis switch-container 状态容器详解:按动态条件渲染多状态内容的 JSON 配置指南
amis switch container 状态容器详解:按动态条件渲染多状态内容的 JSON 配置指南 switch container(状态容器)是 ami
前端低代码UI组件
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考