Refine v5 迁移指南:从 @refinedev/react-router-v6 平滑升级到 React Router v7
【免费下载链接】refineA React Framework for building internal tools, admin panels, dashboards & B2B apps with unmatched flexibility.项目地址: https://gitcode.com/GitHub_Trending/re/refine
本指南基于 documentation/docs/routing/integrations/react-router/migration-guide-v6-to-v7.md,系统讲解如何将基于@refinedev/react-router-v6(React Router v6)的 Refine 项目迁移到@refinedev/react-router(React Router v7)。你将掌握包替换、依赖更新、import 改写的完整步骤,以及如何借助官方refine-codemod一键完成自动迁移,并深入了解新包在仓库源码层面的导出结构与工作原理。
迁移概览:这次升级到底改了什么
对于使用 React Router 的 Refine 项目来说,v6 → v7 的升级核心是一次包层面的重新组织,而不是 API 的大规模重写:
- 包名变更:
@refinedev/react-router-v6更名为@refinedev/react-router,目的是与其他 Refine 集成包的命名保持一致,避免混淆; - 底层依赖变更:React Router 官方在 v7 中将
react-router-dom合并进react-router,因此项目中不再需要安装react-router-dom,所有组件统一从react-router导入; - Refine 自身无破坏性变更:迁移指南明确指出,除包名变化外,Refine 并未引入其他 breaking changes,因此迁移工作的重心是依赖替换与 import 更新。至于 React Router v7 自身的破坏性变化(如 Data APIs、未来标志等),官方建议阅读 React Router v7 的迁移文档进一步确认。
从当前仓库的实际状态看,新包 packages/react-router/package.json 的依赖为react-router: ^7.0.2,peerDependencies 同样要求react-router: ^7.0.2,并且@refinedev/core的 peer 版本为^5.0.0,即新包面向 Refine v5 生态。
第一步:卸载旧包
迁移的第一步是移除旧版相关的三个包。由于 v7 中react-router已合并了原react-router-dom的能力,三者都需要从项目中卸载:
npm uninstall @refinedev/react-router-v6 react-router-dom react-router若项目使用 pnpm 或 yarn,将
npm uninstall替换为对应的pnpm remove或yarn remove即可,原理一致。
第二步:安装新包
卸载完成后,安装新的集成包与 React Router v7。注意这里不再需要安装react-router-dom,所有 v7 组件(RouterProvider、BrowserRouter、Routes、Route、Outlet、Link等)均从react-router包导入:
npm install @refinedev/react-router react-router安装完成后,package.json中的依赖变化对应如下:
- "@refinedev/react-router-v6": "^4.6.0" + "@refinedev/react-router": "^1.0.1" - "react-router-dom": "^6.8.1" - "react-router": "^6.8.1" + "react-router": "^7.0.2"完成以上两步后,基础迁移即告完成,可以开始使用@refinedev/react-router搭配react-routerv7 编写路由。
第三步:更新 import 语句
包替换后,所有相关 import 需要同步更新,主要涉及两类来源:
import routerProvider, { NavigateToResource, UnsavedChangesNotifier, DocumentTitleHandler } - from "@refinedev/react-router-v6"; + from "@refinedev/react-router"; -import { RouterProvider } from "react-router-dom"; +import { RouterProvider } from "react-router";RouterProvider是典型的受影响示例:v6 时代它从react-router-dom导出,v7 中改从react-router导出。除此之外,BrowserRouter、Routes、Route、Outlet、Link、Navigate、useNavigate、useLocation、useParams等组件与 hooks 的导入来源也都应改为react-router。
推荐方案:用 refine-codemod 自动改写 import
手动逐个文件更新 import 容易遗漏,官方推荐使用refine-codemod自动完成替换。该工具基于 jscodeshift 实现源码级 AST 转换,可以精准改写所有命中的 import 声明。使用前请确保 git 工作区干净,以便迁移不符合预期时可以回退。
针对本次迁移,需要依次执行两条 codemod:
# 将 @refinedev/react-router-v6 改写为 @refinedev/react-router npx @refinedev/codemod@latest refine-react-router-v6-to-refine-react-router # 将 react-router-dom 改写为 react-router npx @refinedev/codemod@latest react-router-dom-to-react-router从仓库源码可以确认这两条 codemod 的实际行为:在 packages/codemod/src/index.ts 中注册了对应名称;其转换逻辑分别位于 refine-react-router-v6-to-refine-react-router.ts 与 react-router-dom-to-react-router.ts:
refine-react-router-v6-to-refine-react-router:查找source为@refinedev/react-router-v6的ImportDeclaration,原样保留 import specifiers,仅将模块名替换为@refinedev/react-router;react-router-dom-to-react-router:查找source为react-router-dom的ImportDeclaration,将模块名替换为react-router。
可见两条 codemod 都只做模块来源的精准替换,不会改动你导入的具名符号,迁移后代码语义保持不变。
迁移后的源码级认知:@refinedev/react-router 导出了什么
迁移完成后,新包在仓库中的核心实现位于 packages/react-router/src/index.ts,从中可以看到包的公开导出面,这也是迁移后你在项目中可以继续使用的全部能力:
export { routerProvider as default, stringifyConfig } from "./bindings.js"; export { NavigateToResource } from "./navigate-to-resource.js"; export { UnsavedChangesNotifier } from "./unsaved-changes-notifier.js"; export { CatchAllNavigate } from "./catch-all-navigate.js"; export { DocumentTitleHandler } from "./document-title-handler.js"; export { useDocumentTitle } from "./use-document-title.js";routerProvider(默认导出):传给<Refine routerProvider={routerProvider}>的路由桥接层,实现go、back、parse、Link四个核心能力。其实现位于 bindings.tsx:go基于useNavigate构造目标 URL(支持query、hash、keepQuery、keepHash等配置),parse结合matchResourceFromRoute与qs解析出当前resource、action、id与分页参数,Link直接转发react-router的<Link>;NavigateToResource:跳转到指定资源的 list 页面,常用于应用根路由;UnsavedChangesNotifier:配合options.warnWhenUnsavedChanges: true实现未保存更改的离开提醒(含beforeunload场景);CatchAllNavigate:重定向到指定路径,并将当前 location 以to查询参数保留以便回跳,实现见 catch-all-navigate.tsx;DocumentTitleHandler与useDocumentTitle:按资源与动作自动生成页面标题,也支持自定义handler与 i18n 键。
这些组件的具体用法(含认证路由、布局、Access Control、错误页、根路由等场景)可继续参考 documentation/docs/routing/integrations/react-router/index.md。
迁移后的基本用法验证
完成迁移后,一个最小可用形态如下(演示BrowserRouter风格,均从react-router导入):
import { Refine } from "@refinedev/core"; import dataProvider from "@refinedev/simple-rest"; import routerProvider from "@refinedev/react-router"; import { BrowserRouter, Routes, Route } from "react-router"; import { PostList, PostCreate } from "pages/posts"; const App = () => { return ( <BrowserRouter> <Refine dataProvider={dataProvider} routerProvider={routerProvider} resources={[ { name: "posts", list: "/posts", create: "/posts/create", }, ]} > <Routes> <Route path="posts"> <Route index element={<PostList />} /> <Route path="create" element={<PostCreate />} /> </Route> </Routes> </Refine> </BrowserRouter> ); };若项目使用 React Router v7 的 Data APIs(createBrowserRouter+<RouterProvider>),同样全部从react-router导入即可,routerProvider的传参方式不变。
注意事项与后续动作
- React Router v7 自身的破坏性变更:
@refinedev/react-router只负责 Refine 与 React Router 的桥接,不屏蔽 React Router v7 本身的变更(如未来标志、Data APIs 行为等),迁移后建议按 React Router v7 迁移文档核对项目中直接使用的路由 API; - 版本对齐:从仓库的 package.json 可见,新包要求 Node
>=20、react ^18 || ^19、@refinedev/core ^5.0.0,请确保项目环境满足这些约束; - codemod 的可回退性:自动改写是批量源码修改,执行前务必确认 git 工作区干净,改完后先跑一遍类型检查(
tsc --noEmit)与构建,再提交; - 组件与 hooks 不受影响:
NavigateToResource、UnsavedChangesNotifier、CatchAllNavigate、DocumentTitleHandler、useDocumentTitle的 API 均保持不变,业务代码中除 import 来源外无需额外改动。
至此,你的 Refine 项目已平滑完成从 React Router v6 到 v7 的迁移:包名统一、依赖精简、import 规整,并且可以继续享受 Refine 路由桥接层提供的全部能力。
【免费下载链接】refineA React Framework for building internal tools, admin panels, dashboards & B2B apps with unmatched flexibility.项目地址: https://gitcode.com/GitHub_Trending/re/refine
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考