refine 路由实战(React Router):表单提交与登录鉴权后的页面重定向(Redirects)
refine 路由实战React Router表单提交与登录鉴权后的页面重定向Redirects【免费下载链接】refineA React Framework for building internal tools, admin panels, dashboards B2B apps with unmatched flexibility.项目地址: https://gitcode.com/GitHub_Trending/re/refine本篇围绕 refine 官方教程的 Routing with React Router 系列中的 Redirects 一步展开讲解如何在表单提交成功后自动跳转到列表、详情或编辑页以及如何通过authProvider的redirectTo返回值在登录、登出、报错时完成页面跳转。读完后你将掌握useForm的redirect参数、Refine /组件options.redirect的全局默认配置以及AuthProvider各方法返回结构中redirectTo的用法并能从源码层面理解跳转逻辑是如何被解析和执行的。重定向在 refine 中的整体定位refine 是一个面向内部工具、管理后台、仪表盘与 B2B 应用的 React 框架。路由是其核心能力之一在完成了资源定义resource definition与参数推断parameter inference之后重定向redirect是补齐用户提交表单/登录成功后应该去哪里这一体验缺口的关键机制。refine 可以替你自动管理重定向表单提交成功后refine 会尝试把用户重定向到合适的页面同样地鉴权流程login、logout、onError也可以通过返回redirectTo参数跳转到目标页面——例如登录成功后进入首页、登出成功后回到登录页。本篇基于教程文件 documentation/tutorial/routing/redirects/react-router/index.md其中的可交互示例代码维护在同目录的 documentation/tutorial/routing/redirects/react-router/sandpack.tsx 中可作为完整运行参照。表单提交后的重定向redirect 参数取值与默认值默认情况下refine 会在表单提交成功后把用户重定向到目标资源的列表页。要自定义该行为可以向useForm钩子传入redirect参数。从类型定义看redirect参数的完整取值与默认值在 packages/core/src/hooks/form/types.ts 中有明确声明约 L93-L98/** * Page to redirect after a succesfull mutation * type show | edit | list | create | false * default list */ redirect?: RedirectAction;对应类型RedirectAction定义如下同文件 L35-L37export type RedirectAction | ExtractAction, create | edit | list | show | false;即取值效果list默认跳转到目标资源的列表页show跳转到该记录的详情页edit跳转到该记录的编辑页create跳转到新建页false禁用跳转停留在当前页编辑后跳转到详情页以EditProduct /组件为例向useForm传入redirect: show即可在提交成功后跳转到所编辑产品的详情页。更新src/pages/products/edit.tsximport { useForm, useSelect } from refinedev/core; export const EditProduct () { const { onFinish, mutation, query } useForm({ // This will redirect to the show page after the mutation is successful. // Default value is list. // We can also provide false to disable the redirect. redirect: show, }); /* ... */ };提交逻辑来自教程 sandpack 中的完整实现sandpack.tsx L25-L99表单通过原生FormData收集字段值onFinish负责提交mutation.isSuccess用于展示提交成功提示。编辑页通过query.data?.data读取记录用于回填并通过useSelect({ resource: categories })获取分类下拉选项const record query.data?.data; const { options } useSelect({ resource: categories }); const onSubmit (event: React.FormEventHTMLFormElement) { event.preventDefault(); const data Object.fromEntries(new FormData(event.target).entries()); onFinish({ ...data, price: Number(data.price).toFixed(2), category: { id: Number(data.category) }, }); };创建成功后继续编辑该记录保存并继续编辑save-and-continue是表单类后台的高频需求。在CreateProduct /组件中把redirect设为edit提交成功后用户会被带到新建记录的编辑页可以紧接着创建下一条import { useForm, useSelect } from refinedev/core; export const CreateProduct () { const { onFinish, mutation } useForm({ // We can also provide false to disable the redirect. // Default value is list. redirect: edit, }); /* ... */ };提示useForm的redirect是单表单级配置。若想让应用内所有表单按 action 统一使用默认跳转策略可以改用Refine /组件的options.redirect属性下一节展开。用 的 options.redirect 设置全局默认跳转Refine /组件接受options.redirect配置按表单 action 分别设置默认重定向。从源码看该配置项包含三个字段类型定义在 packages/core/src/contexts/refine/types.tsL114-L118redirect: { afterCreate: RedirectAction; afterClone: RedirectAction; afterEdit: RedirectAction; };这三个值在 packages/core/src/contexts/refine/index.tsx 中的默认值均为listredirect: { afterCreate: list, afterClone: list, afterEdit: list, },也就是说无论创建、克隆还是编辑全局默认都是跳回列表页——这正是教程中默认跳转到列表页说法的来源。重定向的解析优先级源码级视角useForm传入的redirect与Refine /的options.redirect谁生效refine 用一个纯函数redirectPage明确了优先级实现见 packages/core/src/definitions/helpers/redirectPage/index.tsexport const redirectPage ({ redirectFromProps, action, redirectOptions, }: RedirectPageProps): RedirectAction { // 表单级配置含 false优先 if (redirectFromProps || redirectFromProps false) { return redirectFromProps; } // 否则回退到 Refine / 的全局选项 switch (action) { case clone: return redirectOptions.afterClone; case create: return redirectOptions.afterCreate; case edit: return redirectOptions.afterEdit; default: return false; } };由此可以归纳出解析规则useForm({ redirect })参数优先级最高且传入false也能显式禁用跳转注意redirectFromProps false的专门判断undefined才会回退未传时回退到options.redirect中按 action 对应的afterCreate/afterEdit/afterClone该选项的合并逻辑在 packages/core/src/definitions/helpers/handleRefineOptions/index.ts 中完成options.redirect?.afterX未设置时取defaultRefineOptions中的list。而真正执行跳转的是 packages/core/src/hooks/redirection/index.ts 中的useRedirectionAfterSubmission它基于路由上下文提供的导航方法实现const { show, edit, list, create } useNavigation(); if (redirect resource) { if (!!resource.show redirect show id) { return show(resource, id, undefined, meta); } if (!!resource.edit redirect edit id) { return edit(resource, id, undefined, meta); } if (!!resource.create redirect create) { return create(resource, undefined, meta); } return list(resource, push, meta); }从源码结构看有两点值得注意跳转到show/edit前会检查资源是否注册了对应路由!!resource.show/!!resource.edit并且必须有id不满足条件时统一回退到list避免跳到不存在的页面导航方法来自useNavigation底层由路由集成React Router / Next.js / Remix 等 RouterProvider提供因此这套跳转逻辑与具体路由库解耦教程中 React Router 场景的写法同样适用于其他路由集成。Auth Provider 中的重定向refine 为 auth provider 提供了同样简单的路由集成方式在login、logout、onError方法的返回值中提供redirectTo参数即可把用户重定向到合适的页面——例如登录成功后进入首页、登出成功后进入登录页。更新src/providers/auth-provider.ts为login和logout的返回值加上redirectToimport { AuthProvider } from refinedev/core; export const authProvider: AuthProvider { logout: async () { localStorage.removeItem(my_access_token); // Lets redirect to the login page after a successful logout. return { success: true, redirectTo: /login }; }, login: async ({ email, password }) { const response await fetch( https://api.fake-rest.refine.dev/auth/login, { method: POST, body: JSON.stringify({ email, password }), headers: { Content-Type: application/json, }, }, ); const data await response.json(); if (data.token) { localStorage.setItem(my_access_token, data.token); // Lets redirect to the index page after a successful login. return { success: true, redirectTo: / }; } return { success: false }; }, /* ... */ };redirectTo 的类型边界redirectTo并非只有login/logout才能用。从 packages/core/src/contexts/auth/types.ts 的类型定义看三类返回结构都包含可选的redirectTo?: stringexport type CheckResponse { authenticated: boolean; redirectTo?: string; // check 未认证时可跳转如 /not-authenticated logout?: boolean; error?: RefineError | Error; }; export type OnErrorResponse { redirectTo?: string; // onError 处理 401 等错误时可跳转 logout?: boolean; error?: RefineError | Error; }; export type AuthActionResponse { success: boolean; // login / logout / register / redirectTo?: string; // forgotPassword / updatePassword 共用 error?: RefineError | Error; [key: string]: unknown; successNotification?: SuccessNotificationResponse; };check方法的注释同文件 L25-L29进一步说明了典型用法check返回{ authenticated: false, logout: false, redirectTo: /not-authenticated }时用户会被重定向到未授权页但不触发登出返回{ authenticated: false, logout: true, redirectTo: false }时则登出且不做跳转。onError 的完整示例教程 sandpack 中的最终authProvider实现sandpack.tsx L157-L234还展示了onError的写法配合redirectTo使用效果最佳onError: async (error) { if (error?.status 401) { return { logout: true, error: { message: Unauthorized, name: Error, statusCode: error?.status ?? 403, }, }; } return {}; },当接口返回 401 时触发登出登出返回值中的redirectTo: /login会继续生效其他错误则原样吞掉。此外示例还保留了check读取localStorage中的 token 判断认证态、getIdentity等方法的完整实现可直接作为api.fake-rest.refine.dev这套假 REST 服务的对接参照。适用前提与注意事项本篇示例基于教程默认的假数据服务https://api.fake-rest.refine.dev账号密码来自教程前序步骤替换真实后端时只需调整authProvider中的请求地址与字段redirect: show/edit生效的前提是资源在Resource中注册了对应路由且记录id可用否则 refine 会回退到列表页见 packages/core/src/hooks/redirection/index.ts 中的判断逻辑useForm的redirect优先级高于Refine /的options.redirect全局配置只作为默认值存在教程上下文本篇是该系列 redirects 步骤前一步是参数推断documentation/tutorial/routing/inferring-parameters/react-router/index.md下一步将学习如何把当前页表格状态存入 URLdocumentation/tutorial/routing/syncing-state/react-router/index.md。至此你已经掌握了 refine 中表单与鉴权流程的两套重定向机制表单侧通过useForm的redirect参数或Refine /的options.redirect精确控制提交后的去向鉴权侧通过login/logout/onError/check返回结构中的redirectTo完成登录、登出与异常场景的页面流转。【免费下载链接】refineA React Framework for building internal tools, admin panels, dashboards B2B apps with unmatched flexibility.项目地址: https://gitcode.com/GitHub_Trending/re/refine创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考