拓冰建站拓冰建站
首页 / 资讯中心 / 正文

Refine v3 useLogout 钩子深度解析:基于 react-query 封装 authProvider.logout 与登出后的三种重定向策略

Refine v3 useLogout 钩子深度解析基于 react-query 封装 authProvider.logout 与登出后的三种重定向策略【免费下载链接】refineA React Framework for building internal tools, admin panels, dashboards B2B apps with unmatched flexibility.项目地址: https://gitcode.com/GitHub_Trending/re/refine本文以 Refine v3 官方 API 参考中的useLogout文档为主体系统讲解这个数据钩子的定位、与authProvider的协作机制、自定义登出按钮的完整写法以及登出成功后三种重定向策略的取舍并结合当前开源仓库中的源码实现与测试用例剖析该钩子从 v3 到当前版本的演进方向。读完后你能够独立完成自定义登出流程、精确控制登出后的跳转行为并理解其底层基于useMutation的调用链。useLogout 是什么authProvider.logout 的 react-query 封装useLogout是 Refine 认证体系中的一个数据钩子data hook它的底层逻辑是调用authProvider提供的logout方法并将整个登出过程包装成一次 react-query 的 mutation 请求。用一句话概括 v3 版本的行为语义如果authProvider的logout方法resolve无论 resolve 出什么应用即完成登出unauthenticate如果logout方法reject抛出错误认证状态保持不变用户仍处于登录态。它的返回值就是 react-queryuseMutation的完整结果对象——data、mutate、mutateAsync、isPending、isSuccess等字段均可直接使用。其中logout方法 resolve 出来的数据会作为查询结果的data返回这一点正是后文“重定向策略”中“从 promise 中解析出自定义 URL”的技术基础。前提约束只有在提供了authProvider的前提下useLogout才能使用。如果你的应用本身不需要认证则无需关注该钩子。基本用法默认登出按钮与自定义按钮Refine 的默认布局sider已经内置了一个登出按钮如果你使用默认按钮就不需要手动处理登出流程。但如果你的登录/布局是完全自定义的就需要基于useLogout自己实现按钮。这一点可以从仓库中各 UI 包的主题布局源码得到印证以 Ant Design 主题布局为例侧边栏组件内部正是直接消费useLogout来渲染默认退出项的见 packages/antd/src/components/themedLayout/sider/index.tsxconst { mutate: mutateLogout } useLogout();Material UI 的侧边栏 packages/mui/src/components/themedLayout/sider/index.tsx 也是如此。自定义登出按钮的完整写法如下v3 版本从pankod/refine-core导入import { useLogout } from pankod/refine-core; export const LogoutButton () { const { mutate: logout } useLogout(); return button onClick{() logout()}Logout/button; };调用logout()即触发 mutation内部会调用你在Refine组件中配置的authProvider.logout成功后由 Refine 内部完成登出状态的切换与可选的路由跳转。登出后的重定向三种策略的完整梳理useLogout最容易被忽视的部分是登出成功之后应用跳向哪里。v3 提供了三种互斥的策略全部围绕logout方法返回的 promise 展开。策略一默认跳转/login如果logout返回的 promiseresolve 时不携带任何值即 resolveundefined/null应用会默认被重定向到/login路由。这是最常见的“登出即回登录页”行为也是绝大多数后台管理系统的默认预期。策略二从authProvider.logout的返回值中解析自定义 URL如果logout方法需要把用户带到一个非登录页的地址例如统一的“感谢使用”页、SSO 注销页可以让logout方法 resolve 一个字符串 URLconst authProvider: AuthProvider { ... logout: () { ... return Promise.resolve(/custom-url); } }由于logoutresolve 的数据会原样进入 mutation 结果的dataRefine 在 v3 中会识别这个字符串并执行跳转。策略三从useLogout的 mutate 函数传入 redirectPath如果跳转地址应该在调用侧决定而不是写死在authProvider里可以直接给mutate传入一个对象import { useLogout } from pankod/refine-core; const { mutate: logout } useLogout{ redirectPath: string }(); logout({ redirectPath: /custom-url });传入的redirectPath会作为参数交给authProvider.logout方法你可以在其中把它解析为返回值const authProvider: AuthProvider { ... logout: ({ redirectPath }) { ... return Promise.resolve(redirectPath); } }注意优先级调用侧通过mutate传入的自定义 URL 会覆盖authProvider.logout返回值中的 URL。也就是说redirectPath参数具有最高优先级。策略四特殊值resolvefalse表示不跳转如果logout方法返回的 promise resolve 为false则不发生任何重定向——适合那些登出后仍需停留在当前页面例如游客态可以继续浏览的场景const authProvider: AuthProvider { ... logout: () { ... return Promise.resolve(false); } }参数灵活性的提示useLogout取到的mutate函数可以接受任意形态的对象作为参数因为authProvider的logout方法本身对入参没有类型限制。你可以传redirectPath也可以传任何你的logout实现需要处理的自定义字段useLogout只做透传。源码印证从仓库实现看 useLogout 的完整调用链v3 文档描述的是当时的行为约定当前仓库主分支对应 v4 及以后的版本中该钩子的完整实现位于 packages/core/src/hooks/auth/useLogout/index.ts可以从中看到它的实现骨架以及语义演进mutation 封装钩子内部调用useMutation来自tanstack/react-querymutationFn直接取自useAuthProviderContext()的logout方法即文档所述“底层调用authProvider.logout”在源码中成立重定向裁决逻辑见该文件onSuccess回调约 L66-L91const { redirectPath } variables ?? {}; const redirect redirectPath ?? redirectTo; if (redirect ! false) { if (redirect) { go({ to: redirect }); } }redirectPath ?? redirectTo的写法正是文档中“调用侧 URL 覆盖authProviderURL”这一优先级的源码体现redirect ! false分支则对应“resolvefalse不跳转”的语义。路由跳转通过useGo钩子即routerProvider的go执行 3.登出后的缓存失效无论是否跳转onSuccess末尾都会调用invalidateAuthStore()。从 packages/core/src/hooks/auth/useInvalidateAuthStore/index.ts 的源码看它会并行invalidateQueries三个认证相关查询check、identity、permissions——这保证了登出后菜单权限、用户身份、认证状态不会残留旧缓存 4.可注入的 mutationOptions当前版本还接受{ mutationOptions }参数允许覆盖 react-query 的 mutation 配置测试用例中验证了mutationFn、mutationKey均可被覆盖。值得说明的是当前仓库中logout方法的响应结构已从 v3 的“void | false | string”演进为结构化的AuthActionResponse定义见 packages/core/src/contexts/auth/types.tsexport type AuthActionResponse { success: boolean; redirectTo?: string; error?: RefineError | Error; successNotification?: SuccessNotificationResponse; [key: string]: unknown; };即“是否登出成功、跳转到哪里、错误信息、成功提示”被显式建模为字段redirectTo对应本文策略二而不再依赖 resolve 值的隐式约定。迁移到新版本的authProvider写法时可参考 迁移指南。测试用例对行为边界的验证针对该钩子的测试文件 packages/core/src/hooks/auth/useLogout/index.spec.ts 用一组用例锁定了行为边界与文档描述逐条对应可作为验收标准logout and redirect to loginlogout返回redirectTo: /login时断言路由go被以{ to: /login }调用logout and not redirect返回{ success: true }且无redirectTo时断言go未被调用即“无重定向目标则不跳转”pass redirect with hooks param/pass redirect with authProvider return value分别验证了策略三调用侧redirectPath: /custom-path与策略二返回redirectTo都能正确触发跳转间接覆盖了“redirectPath优先”的裁决逻辑;logout rejected系列success: false时data携带错误信息且不发生跳转与文档“reject 保持认证状态”的语义一致通知行为失败时通过notificationProvider.open打开key: useLogout-error的错误通知返回successNotification时打开key: logout-success的成功通知。这些用例同时说明即使logout逻辑内部抛错onError分支钩子也会兜底弹出默认的错误通知message: Errordescription取error.message不会让异常静默消失。小结useLogout的价值在于把“调用authProvider.logout→ 切换认证状态 → 按策略重定向 → 失效认证缓存”这条链路收敛到一次 mutation 调用中。使用它时把握三个决策点即可用默认 sider 按钮还是自定义按钮——后者只需const { mutate: logout } useLogout()登出后去哪里——默认/login、authProvider返回自定义 URL、调用侧传redirectPath优先级最高、或false取消跳转前提——必须提供authProvider且logout方法的成功/失败语义v3 以 promise resolve/reject 表达当前版本以AuthActionResponse.success表达要与版本匹配。【免费下载链接】refineA React Framework for building internal tools, admin panels, dashboards B2B apps with unmatched flexibility.项目地址: https://gitcode.com/GitHub_Trending/re/refine创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门