CHANGELOG.md
本页内容

React Router 版本发布

此页面列出了 React Router 自 v6.0.0 以来的所有版本发布/发布说明。对于 v6 之前的版本,请参考 Github 版本发布页面

我们在此文件中管理版本发布说明,而不是分页的 Github 版本发布页面,原因有 2 个:

  • Github UI 中的分页意味着您无法轻松搜索大跨度版本的发布说明
  • 分页的 Github 界面还会截断较长的版本发布说明,且列表视图中没有指示,您需要点击进入详细视图才能查看完整的版本发布说明
目录

v7.2.0

日期:2025-02-18

变更内容

类型安全的 href 实用程序

在框架模式下,我们现在为您提供完全类型安全的 href 实用程序,为您提供路径自动完成和参数验证的温馨舒适感,用于应用程序中的链接

import { href } from "react-router";

export default function Component() {
  const link = href("/blog/:slug", { slug: "my-first-post" });
  //                ^ type-safe!     ^ Also type-safe!

  return (
    <main>
      <Link to={href("/products/:id", { id: "asdf" })} />
      <NavLink to={href("/:lang?/about", { lang: "en" })} />
    </main>
  );
}

如果您传递错误的路径值或错误的参数值,您现在将收到类型错误

const badPath = href("/not/a/valid/path");
//                   ^ Error!

const badParam = href("/blog/:slug", { oops: "bad param" });
//                                     ^ Error!

使用 SPA 回退进行预渲染

此版本增强了在 ssr:false 预渲染时,将预渲染路径与其他以“SPA 模式”运行的路径结合使用的能力。

  • 如果您指定 ssr:false 而没有 prerender 配置,则这被视为“SPA 模式”,并且生成的 index.html 文件将仅渲染到根路由,并且能够为任何有效的应用程序路径进行水合
  • 如果您指定 ssr:false 并带有 prerender 配置,但包含 / 路径(即 prerender: ['/blog/post']),那么我们仍然生成一个“SPA 模式”index.html 文件,该文件可以为应用程序中的任何路径进行水合
  • 如果您指定 ssr:false 并在您的 prerender 配置中包含 / 路径,则生成的 index.html 文件将特定于根索引路由,因此我们现在还将在 __spa-fallback.html 中生成一个单独的“SPA 模式”文件,您可以为非预渲染路径提供服务/水合

有关更多信息,请参阅 预渲染 文档以获取更多信息。

允许在 SPA 模式下使用根 loader

SPA 模式过去禁止在所有路由中使用 loader,以便我们可以为应用程序中的任何路径进行水合。但是,由于根路由始终在构建时渲染,因此我们可以解除对根路由的此限制。

为了在预渲染期间使用您的构建时 loader 数据,我们现在还将 loaderData 公开为路由上 HydrateFallback 组件的可选属性

  • 只要 HydrateFallback 正在渲染,因为路由正在加载,这将是已定义的
  • 如果 HydrateFallback 正在渲染,因为路由本身有自己的水合 clientLoader,这将是 undefined
    • 在 SPA 模式下,这将允许您将 loader 根数据渲染到 SPA 模式 HTML 文件中

次要变更

  • react-router - 新的类型安全 href 实用程序,保证链接指向应用程序中的实际路径 (#13012)
  • @react-router/dev - 在使用 ssr:false 预渲染 / 路由时,生成“SPA 回退”HTML 文件 (#12948)
  • @react-router/dev - 允许在 SPA 模式下的根路由中使用 loader,因为它可以在构建时被调用/服务器渲染 (#12948)
    • Route.HydrateFallbackProps 现在也接收 loaderData

补丁变更

  • react-router - 对所有 ssr:false 应用程序(而不仅仅是“SPA 模式”)禁用惰性路由发现,因为没有运行时服务器来服务搜索参数配置的 __manifest 请求 (#12894)
    • 我们之前仅对“SPA 模式”禁用了此功能,但我们意识到它应该适用于所有 ssr:false 应用程序
    • 在这些 prerender 场景中,我们将预渲染 /__manifest 文件,但这会对静态文件服务器行为做出一些不必要的假设
  • react-router - 在 SPA 模式下,由于没有服务器 HTTP 请求,因此不应用单次获取重新验证反优化 (#12948)
  • react-router - 正确处理跨预渲染/SPA 边界的重新验证 (#13021)
    • 在“混合”应用程序中,某些路由是预渲染的,而某些路由是从 SPA 回退提供的,如果路径未预渲染,我们需要避免发出 .data 请求,因为该请求将返回 404
    • 但是,我们不知道客户端的所有预渲染路径
      • ssr:false 模式下的所有 loader 数据都是静态的,因为它是在构建时生成的
      • 路由必须使用 clientLoader 才能执行任何动态操作
      • 因此,如果路由仅具有 loader 而没有 clientLoader,我们默认禁用重新验证,因为没有新数据要检索
      • 如果我们的单次获取 dataStrategy 中没有 shouldLoad=true 的服务器加载器,我们将短路并跳过单次获取 .data 请求逻辑
      • 这确保了路由不会导致在提交后返回 404 的 .data 请求
  • react-router - 当设置 ssr:false 时,使开发服务器行为与静态文件服务器行为对齐 (#12948)
    • 当不存在 prerender 配置时,仅 SSR 到根 HydrateFallback (SPA 模式)
    • 当存在 prerender 配置但当前路径未预渲染时,仅 SSR 到根 HydrateFallback (SPA 回退)
    • 在对非预渲染路径的 .data 请求上返回 404
  • react-router - 提高框架模式下 CSS 副作用的预取性能 (#12889)
  • react-router - 正确处理惰性路由发现中中断的 manifest 请求 (#12915)
  • @react-router/dev - 处理 Vite 配置中的自定义 envDir (#12969)
  • @react-router/dev - 修复 CLI 解析,以允许无参数 npx react-router 用法 (#12925)
  • @react-router/dev - 使用 prerender:true 时跳过仅操作的资源路由 (#13004)
  • @react-router/dev - 增强使用 ssr:false 时的无效导出检测 (#12948)
    • 在所有 ssr:false 路由中都禁止使用 headers/action 函数,因为将没有运行时服务器来运行它们
    • loader 函数更加细致,并且取决于给定的路由是否预渲染
      • 当使用没有 prerender 配置的 ssr:false 时,只有 root 路由可以具有 loader
      • 当使用带有 prerender 配置的 ssr:false 时,只有与 prerender 路径匹配的路由可以具有 loader
  • @react-router/dev - 在 ssr:false + prerender 应用程序中,针对以下边缘情况在构建时报错: (#13021)
    • 父路由仅具有 loader(没有 clientLoader
    • 父路由是预渲染的
    • 父路由具有未预渲染的子路由
    • 这意味着当通过 SPA 回退加载子路径时,父路由将没有任何 loaderData,因为没有服务器来运行 loader
    • 这可以通过添加父 clientLoader 或预渲染子路径来解决
    • 如果您添加 clientLoader,则在非预渲染路径上调用 serverLoader() 将抛出 404 错误
  • @react-router/dev - 将预渲染资源路由 .data 文件限制为仅目标路由 (#13004)
  • @react-router/dev - 修复二进制文件的预渲染 (#13039)
  • @react-router/dev - 修复重复参数的类型生成 (#13012)
    • 在 React Router 中,路径参数按其名称键控,因此对于像 /a/:id/b/:id?/c/:id 这样的路径模式,最后一个 :id 将在 useParamsparams 属性中设置 id 的值
      • 例如,/a/1/b/2/c/3 将在运行时产生值 { id: 3 }
    • 以前,为参数生成的类型错误地将重复参数建模为数组
      • 例如,/a/1/b/2/c/3 生成了类似 { id: [1,2,3] } 的类型。
    • 为了与运行时行为保持一致,生成的类型现在正确地将路径参数的“最后一个获胜”语义建模。
      • 例如,/a/1/b/2/c/3 现在生成了类似 { id: 3 } 的类型。
  • @react-router/dev - 修复加载 package.json 的路径,用于 react-router --version (#13012)

不稳定变更

  • react-router - 添加 unstable_SerializesTo 品牌类型,供库作者注册可由 React Router 的流式格式 (turbo-stream) 序列化的类型 (#12264)
  • @react-router/dev - 通过 future.unstable_splitRouteModules 添加对在框架模式下拆分路由模块的不稳定支持 (#11871)
  • @react-router/dev - 添加 future.unstable_viteEnvironmentApi 标志以启用实验性的 Vite Environment API 支持 (#12936)

按包变更

完整更新日志: v7.1.5...v7.2.0

v7.1.5

日期:2025-01-31

补丁变更

  • react-router - 修复了通过 #128007.1.4 中引入的回归,该回归导致在使用惰性路由发现 (patchRoutesOnNavigation) 的应用程序中,导航到 splat 路由内的哈希路由时出现问题 (#12927)

完整更新日志: v7.1.4...v7.1.5

v7.1.4

日期:2025-01-30

补丁变更

  • @react-router/dev - 使用 unstable_optimizeDeps 未来特性标志时,正确解析 Windows 文件路径以扫描 Vite 的依赖项优化 (#12637)
  • @react-router/dev - 修复使用自定义服务器时的预渲染 - 之前我们最终尝试导入用户的自定义服务器,而实际上我们想要导入虚拟服务器构建模块 (#12759)
  • react-router - 正确处理单次获取响应中不能有主体的状态码(204 等)(#12760)
  • react-router - 在抛出 data() 结果时,正确地将标头作为 errorHeaders 冒泡 (#12846)
    • 如果也从 headers 返回,则避免重复 Set-Cookie 标头
  • react-router - 停止对返回原始字符串/对象的资源路由报错,而是将它们序列化为 text/plainapplication/json 响应 (#12848)
    • 这仅在作为没有 .data 扩展名的资源路由访问时适用
    • 当从单次获取 .data 请求访问时,它们仍将通过 turbo-stream 编码
  • react-router - 优化惰性路由发现路径发现,以支持在 body 级别进行单个 querySelectorAll 调用,而不是在子树级别进行多次调用 (#12731)
  • react-router - 通过在可能的情况下跳过冗余的 matchRoutes 调用来优化路由匹配 (#12800, #12882)
  • react-router - 内部重组以清理一些重复的路由模块类型 (#12799)

完整更新日志: v7.1.3...v7.1.4

v7.1.3

日期:2025-01-17

补丁变更

  • @react-router/dev - 修复 revealroutes CLI 命令 (#12745)

完整更新日志: v7.1.2...v7.1.3

v7.1.2

日期:2025-01-16

补丁更新

  • react-router - 修复了 fetcher 卸载时数据层中 fetcher 数据清理的问题 (#12681)
  • react-router - 不再依赖 symbol 来过滤加载器数据中的 redirect 响应 (#12694)
    • 之前,一些项目遇到了如下类型检查错误
      error TS4058: Return type of exported function has or is using name 'redirectSymbol' from external module "node_modules/..." but cannot be named.
      
    • 现在 symbol 不再用于 redirect 响应类型,这些错误应该不会再出现
  • @react-router/dev - 修复 Vite v6 中的默认外部条件 (#12644)
    • 这修复了某些 npm 包的解析问题
  • @react-router/dev - 修复了路径缺少前导斜杠时预渲染 html/data 文件不匹配的问题 (#12684)
  • @react-router/dev - 在运行时启用 module-sync 服务器条件。这修复了 Node 22.10.0+ 开发中使用对 React Router 有对等依赖的库时,React 上下文不匹配的问题(例如,useHref() may be used only in the context of a <Router> component.)。(#12729)
  • @react-router/dev - 修复 react-refresh source maps (#12686)

完整更新日志: v7.1.1...v7.1.2

v7.1.1

日期:2024-12-23

补丁更新

  • @react-router/dev - 修复了将可选参数传递给 CLI 时崩溃的问题 (#12609)

完整更新日志: v7.1.0...v7.1.1

v7.1.0

日期:2024-12-20

小版本更新

  • 添加对 Vite v6 的支持 (#12469)

补丁更新

  • react-router - 抛出解包后的 Single Fetch redirect 以与 Single Fetch 之前的行为保持一致 (#12506)
  • react-router - 在推断加载器数据类型时忽略重定向 (#12527)
  • react-router - 移除 <Link prefetch> 警告,该警告在懒加载路由发现的世界中容易出现误报 (#12485)
  • create-react-router - 修复了 fs-extra 依赖缺失的问题 (#12556)
  • @react-router/dev/@react-router/serve - 正确初始化 NODE_ENV(如果尚未设置),以兼容 React 19 (#12578)
  • @react-router/dev - 从 ServerRouter 中删除剩余/未使用的 abortDelay 属性,并更新默认的 entry.server.tsx 以使用 Single Fetch 的新 streamTimeout 值 (#12478)
    • abortDelay 功能已在 v7 中删除,因为它与 Remix v2 的 defer 实现耦合,但此属性的删除被遗漏了
    • 如果您仍在 entry.server 文件中使用此属性,则您的应用程序可能无法按预期中止流,您将需要采用使用 Single Fetch 引入的新 streamTimeout
  • @react-router/fs-routes - 如果路由目录缺失,则在 flatRoutes 中抛出错误 (#12407)

按包变更

完整更新日志: v7.0.2...v7.1.0

v7.0.2

日期:2024-12-02

补丁更新

  • react-router - 临时仅在导出映射中使用一个构建版本,以便包可以对 react router 具有对等依赖 (#12437)
  • @react-router/dev - 支持 moduleResolution Node16NodeNext (#12440)
  • @react-router/dev - 为子路由生成宽泛的 matchesparams 类型 (#12397)
    • 在运行时,matches 包括子路由匹配项,params 包括子路由路径参数
    • 但之前,我们仅在 matchesparams 中为父路由和当前路由生成类型
    • 为了使我们生成的类型更接近运行时行为,我们在访问子路由信息时,现在生成更宽松、更宽泛的类型

完整更新日志: v7.0.1...v7.0.2

v7.0.1

日期:2024-11-22

补丁更新

  • @react-router/dev - 确保在 Vite 开发服务器重启时清理类型生成文件监视器 (#12331)
  • @react-router/dev - 将路由 error 作为 prop 传递给 ErrorBoundary (#12338)

完整更新日志: v7.0.0...v7.0.1

v7.0.0

日期:2024-11-21

重大变更

包重构

  • react-router-dom@remix-run/react@remix-run/server-runtime@remix-run/router 已合并到 react-router 包中
    • 为了方便迁移,react-router-dom 在 v7 中仍然作为 react-router 中所有内容的重新导出发布
  • @remix-run/cloudflare-pages@remix-run/cloudflare-workers 已合并到 @react-router/cloudflare 包中`
  • react-router-dom-v5-compatreact-router-native 包已从 v7 开始移除

移除适配器重新导出

Remix v2 过去常常通过各种运行时包(nodecloudflaredeno)重新导出所有常见的 @remix-run/server-runtime API,这样您就不需要在 package.json 中添加额外的 @remix-run/server-runtime 依赖项。随着包合并到 react-router 中,这些常见的 API 现在不再通过运行时适配器重新导出。您应该从 react-router 导入所有常见的 API,而仅从运行时包导入特定于运行时的 API

// Runtime-specific APIs
import { createFileSessionStorage } from "@react-router/node";
// Runtime-agnostic APIs
import { redirect, useLoaderData } from "react-router";

移除的 API

React Router v7 中已移除以下 API

  • json
  • defer
  • unstable_composeUploadHandlers
  • unstable_createMemoryUploadHandler
  • unstable_parseMultipartFormData

最低版本要求

React Router v7 需要以下最低版本

  • node@20
    • React Router 不再提供 installGlobals 方法来 polyfill fetch API
  • react@18, react-dom@18

采纳的未来标志行为

Remix 和 React Router 遵循 API 开发策略,利用“未来标志”来避免在主要版本中引入大量重大变更。相反,重大变更在次要版本中通过标志引入,允许用户在其方便时选择加入。在下一个主要版本中,所有未来标志行为都将成为默认行为。

以下先前标记的行为现在是 React Router v7 中的默认行为

  • React Router v6 标志
    • future.v7_relativeSplatPath
    • future.v7_startTransition
    • future.v7_fetcherPersist
    • future.v7_normalizeFormMethod
    • future.v7_partialHydration
    • future.v7_skipActionStatusRevalidation
  • Remix v2 标志
    • future.v3_fetcherPersist
    • future.v3_relativeSplatPath
    • future.v3_throwAbortReason
    • future.v3_singleFetch
    • future.v3_lazyRouteDiscovery
    • future.v3_optimizeDeps

Vite 编译器

Remix Vite 插件 是使用 React Router v7 构建全栈 SSR 应用程序的正确方法。以前基于 esbuild 的编译器不再可用。

重命名 vitePlugincloudflareDevProxyVitePlugin

对于迁移到 React Router 的 Remix 用户,vitePlugincloudflareDevProxyVitePlugin 导出已重命名并移动 (#11904)

-import {
-  vitePlugin as remix,
-  cloudflareDevProxyVitePlugin,
-} from "@remix/dev";

+import { reactRouter } from "@react-router/dev/vite";
+import { cloudflareDevProxy } from "@react-router/dev/vite/cloudflare";

移除 manifest 选项

对于迁移到 React Router 的 Remix 用户,Vite 插件的 manifest 选项已被移除。manifest 选项已被更强大的 buildEnd 钩子取代,因为它传递了 buildManifest 参数。如果需要,您仍然可以将构建清单写入磁盘,但您很可能会发现将任何依赖于构建清单的逻辑写入 buildEnd 钩子本身更方便。(#11573)

如果您正在使用 manifest 选项,您可以使用 buildEnd 钩子替换它,该钩子将清单写入磁盘,如下所示

// react-router.config.ts
import { type Config } from "@react-router/dev/config";
import { writeFile } from "node:fs/promises";

export default {
  async buildEnd({ buildManifest }) {
    await writeFile(
      "build/manifest.json",
      JSON.stringify(buildManifest, null, 2),
      "utf-8"
    );
  },
} satisfies Config;

暴露的 Router Promise

由于 React 19 将首次支持在渲染过程中处理 promise(通过 React.useuseAction),我们现在可以放心地公开先前返回 undefined 的 API 的 promise

  • useNavigate()
  • useSubmit()
  • useFetcher().load
  • useFetcher().submit
  • useRevalidator().revalidate()

其他值得注意的变更

routes.ts

当使用 React Router Vite 插件时,路由在 app/routes.ts 中定义。路由配置通过 routes 导出,符合 RouteConfig 类型。路由辅助函数 routeindexlayout 提供更轻松地进行声明式类型安全路由定义。

// app/routes.ts
import {
  type RouteConfig,
  route,
  index,
  layout,
} from "@react-router/dev/routes";

export const routes: RouteConfig = [
  index("./home.tsx"),
  route("about", "./about.tsx"),

  layout("./auth/layout.tsx", [
    route("login", "./auth/login.tsx"),
    route("register", "./auth/register.tsx"),
  ]),

  route("concerts", [
    index("./concerts/home.tsx"),
    route(":city", "./concerts/city.tsx"),
    route("trending", "./concerts/trending.tsx"),
  ]),
];

对于迁移到 React Router 的 Remix 用户,您仍然可以使用 @react-router/fs-routes 包在 routes.ts 中配置文件系统路由。重现默认 Remix 设置的最小路由配置如下所示

// app/routes.ts
import { type RouteConfig } from "@react-router/dev/routes";
import { flatRoutes } from "@react-router/fs-routes";

export const routes: RouteConfig = flatRoutes();

如果您想从文件系统路由迁移到基于配置的路由,您可以通过将异步 flatRoutes 函数的结果扩展到基于配置的路由数组中来混合和匹配方法。

// app/routes.ts
import { type RouteConfig, route } from "@react-router/dev/routes";
import { flatRoutes } from "@react-router/fs-routes";

export const routes: RouteConfig = [
  // Example config-based route:
  route("/hello", "./routes/hello.tsx"),

  // File system routes scoped to a different directory:
  ...(await flatRoutes({
    rootDirectory: "fs-routes",
  })),
];

如果您使用 Remix 的 routes 选项来使用替代文件系统路由约定,您可以使用 @react-router/remix-config-routes-adapter 将这些约定适配到新的 RouteConfig 格式。

例如,如果您在 Remix v2 中使用 Remix v1 路由约定,您可以将 @react-router/remix-config-routes-adapter@remix-run/v1-route-convention 结合使用,将其适配到 React Router

// app/routes.ts
import { type RouteConfig } from "@react-router/dev/routes";
import { remixConfigRoutes } from "@react-router/remix-config-routes-adapter";
import { createRoutesFromFolders } from "@remix-run/v1-route-convention";

export const routes: RouteConfig = remixConfigRoutes(async (defineRoutes) => {
  return createRoutesFromFolders(defineRoutes, {
    ignoredFilePatterns: ["**/.*", "**/*.css"],
  });
});

另请注意,如果您使用 Remix 的 routes 选项来定义基于配置的路由,您也可以使用 @react-router/remix-config-routes-adapter 将这些路由适配到新的 RouteConfig 格式,只需进行最少的代码更改。虽然这提供了一条快速迁移路径,但我们建议将 Remix 中任何基于配置的路由迁移到新的 RouteConfig 格式,因为这是一个相当简单的迁移。

// app/routes.ts
-import { type RouteConfig } from "@react-router/dev/routes";
+import { type RouteConfig, route } from "@react-router/dev/routes";
-import { remixConfigRoutes } from "@react-router/remix-config-routes-adapter";

-export const routes: RouteConfig = remixConfigRoutes(async (defineRoutes) => {
-  defineRoutes((route) => {
-    route("/parent", "./routes/parent.tsx", () => [
-      route("/child", "./routes/child.tsx"),
-    ]);
-  });
-});
+export const routes: RouteConfig = [
+  route("/parent", "./routes/parent.tsx", [
+    route("/child", "./routes/child.tsx"),
+  ]),
+];

类型安全改进

React Router 现在为每个路由模块生成类型,并将类型化的 props 传递给路由模块组件导出 (#11961, #12019)。您可以通过从 ./+types/<route filename without extension> 导入它们来访问这些类型。

有关更多详细信息,请参阅 操作指南 > 路由模块类型安全解释 > 类型安全

预渲染

React Router v7 在 vite 插件中包含一个新的 prerender 配置,以支持 SSG 用例。这将在构建时预渲染您的 .html.data 文件,以便您可以在运行时从正在运行的服务器或 CDN 静态地提供它们 (#11539)

export default defineConfig({
  plugins: [
    reactRouter({
      async prerender({ getStaticPaths }) {
        let slugs = await fakeGetSlugsFromCms();
        return [
          ...getStaticPaths(),
          ...slugs.map((slug) => `/product/${slug}`),
        ];
      },
    }),
    tsconfigPaths(),
  ],
});

async function fakeGetSlugsFromCms() {
  await new Promise((r) => setTimeout(r, 1000));
  return ["shirt", "hat"];
}

重大变更 (react-router)

  • 移除原始的 defer 实现,转而使用通过 single fetch 和 turbo-stream 的原始 promise (#11744)
    • 这从 React Router 中移除了以下导出
      • defer
      • AbortedDeferredError
      • type TypedDeferredData
      • UNSAFE_DeferredData
      • UNSAFE_DEFERRED_SYMBOL
  • 将包合并到 react-router 中(#11505)
    • @remix-run/router
    • react-router-dom
    • @remix-run/server-runtime
    • @remix-run/testing
    • 请注意,react-router-dom 包是为了方便采用而维护的,但它只是重新导出了 react-router 中的所有 API
  • 放弃对 Node 16 的支持,React Router SSR 现在需要 Node 18 或更高版本 (#11391, #11690)
  • 移除 future.v7_startTransition 标志 (#11696)
  • 从以下 API 公开底层路由器 promise,以便在 React 19 API 中进行组合:(#11521)
  • 移除 future.v7_normalizeFormMethod 未来标志 (#11697)
  • 导入/导出清理 (#11840)
    • 移除了以下先前来自 @remix-run/router 的公共 API 导出
      • types
        • AgnosticDataIndexRouteObject
        • AgnosticDataNonIndexRouteObject
        • AgnosticDataRouteMatch
        • AgnosticDataRouteObject
        • AgnosticIndexRouteObject
        • AgnosticNonIndexRouteObject
        • AgnosticRouteMatch
        • AgnosticRouteObject
        • TrackedPromise
        • unstable_AgnosticPatchRoutesOnMissFunction
        • Action -> 通过 react-router 导出为 NavigationType
        • Router 导出为 RemixRouter 以区别于 RR 的 <Router>
      • API
        • getToPathname (@private)
        • joinPaths (@private)
        • normalizePathname (@private)
        • resolveTo (@private)
        • stripBasename (@private)
        • createBrowserHistory -> 赞成使用 createBrowserRouter
        • createHashHistory -> 赞成使用 createHashRouter
        • createMemoryHistory -> 赞成使用 createMemoryRouter
        • createRouter
        • createStaticHandler -> 赞成使用 RR Dom 中的包装器 createStaticHandler
        • getStaticContextFromError
    • 移除了以下先前来自 react-router 的公共 API 导出
      • Hash
      • Pathname
      • Search
  • 从内部化的 @remix-run/router 包中移除 future.v7_prependBasename (#11726)
  • 从内部化的 @remix-run/router 包中移除 future.v7_throwAbortReason (#11728)
  • 向所有包添加 exports 字段 (#11675)
  • RemixContext 重命名为 FrameworkContext (#11705)
  • 将最低 React 版本更新为 18 (#11689)
  • PrefetchPageDescriptor 替换为 PageLinkDescriptor (#11960)
  • 移除 future.v7_partialHydration 标志 (#11725)
    • 这也移除了 <RouterProvider fallbackElement> prop
      • 要迁移,请将 fallbackElement 移动到根路由上的 hydrateFallbackElement/HydrateFallback
    • 还值得注意的是,此未来标志存在相关的重大变更
      • 在没有 future.v7_partialHydration 的情况下(当使用 fallbackElement 时),state.navigation 在初始加载期间被填充
      • 使用 future.v7_partialHydrationstate.navigation 在初始加载期间保持 "idle" 状态
  • 移除 future.v7_relativeSplatPath 未来标志 (#11695)
  • 移除剩余的未来标志 (#11820)
    • React Router v7_skipActionErrorRevalidation
    • Remix v3_fetcherPersist, v3_relativeSplatPath, v3_throwAbortReason
  • createRemixStub 重命名为 createRoutesStub (#11692)
  • 移除 @remix-run/router 中已弃用的 detectErrorBoundary 选项,赞成使用 mapRouteProperties (#11751)
  • 添加 react-router/dom 子路径导出,以正确启用 react-dom 作为可选的 peerDependency (#11851)
    • 这确保了我们不会在 <RouterProvider> 中盲目地 import ReactDOM from "react-dom" 以访问 ReactDOM.flushSync(),因为这会在非 DOM 环境中破坏 createMemoryRouter 用例
    • DOM 环境应从 react-router/dom 导入以获取使 ReactDOM.flushSync() 可用的正确组件
      • 如果您正在使用 Vite 插件,请在您的 entry.client.tsx 中使用此方法
        • import { HydratedRouter } from 'react-router/dom'
      • 如果您未使用 Vite 插件并且正在手动调用 createBrowserRouter/createHashRouter
        • import { RouterProvider } from "react-router/dom"
  • 移除 future.v7_fetcherPersist 标志 (#11731)
  • 允许从加载器和 action 返回 undefined (#11680, #12057)
  • entry.client 中使用 createRemixRouter/RouterProvider 而不是 RemixBrowser (#11469)
  • 移除已弃用的 json 实用程序 (#12146)
    • 如果您仍然需要在您的应用程序中构建 JSON 响应,您可以使用 Response.json

重大变更 (@react-router/*)

  • 移除 future.v3_singleFetch 标志 (#11522)
  • 放弃对 Node 16 和 18 的支持,将最低 Node 版本更新为 20 (#11690, #12171)
    • 移除 installGlobals(),因为这不再是必要的
  • 向所有包添加 exports 字段 (#11675)
  • 不再通过不同的运行时/适配器包重新导出 react-router 中的 API (#11702)
  • 对于迁移到 React Router 的 Remix 用户,当使用 cookie 和 session API 时,现在需要 Web Crypto API 中的 crypto 全局变量
    • 这意味着以下 API 由 react-router 而不是特定于平台的包提供:(#11837)
      • createCookie
      • createCookieSessionStorage
      • createMemorySessionStorage
      • createSessionStorage
    • 对于运行旧版本 Node 的用户,@remix-run/node 中的 installGlobals 函数已更新为定义 globalThis.crypto,使用 Node 的 require('node:crypto').webcrypto 实现
    • 由于特定于平台的包不再需要实现此 API,因此以下底层 API 已移除
      • createCookieFactory
      • createSessionStorageFactory
      • createCookieSessionStorageFactory
      • createMemorySessionStorageFactory
  • 合并先前在 @remix-run/router@remix-run/server-runtime@remix-run/react 中重复的类型,因为它们现在都位于 react-router 中 (#12177)
    • 示例:LoaderFunctionLoaderFunctionArgsActionFunctionActionFunctionArgsDataFunctionArgsRouteManifestLinksFunctionRouteEntryRoute
    • “remix”代码使用的 RouteManifest 类型现在更加严格,因为它使用了之前的 @remix-run/router RouteManifest
      • Record<string, Route> -> Record<string, Route | undefined>
    • 移除 AppData 类型,赞成在少数使用它的位置内联 unknown
    • 移除 ServerRuntimeMeta* 类型,赞成使用它们重复自的 Meta* 类型
  • 将 Remix v2 类型泛型迁移到 React Router (#12180)
    • 这些泛型是为 Remix v2 迁移目的提供的
    • 这些泛型及其存在的 API 应被视为非正式弃用,赞成使用新的 Route.* 类型
    • 任何从 React Router v6 迁移的用户可能都不应利用这些新泛型,而应直接迁移到 Route.* 类型
    • 对于 React Router v6 用户,这些泛型是新的,不应影响您的应用程序,但有一个例外
      • useFetcher 之前有一个可选泛型(主要由 Remix v2 使用),它期望数据类型
      • 这已在 v7 中更新为期望生成数据的函数的类型(即 typeof loader/typeof action
      • 因此,您应该更新您的用法
        • useFetcher<LoaderData>()
        • useFetcher<typeof loader>()
  • cookie 依赖项更新为 ^1.0.1 - 请参阅 发行说明 以了解任何重大变更 (#12172)
  • @react-router/cloudflare - 对于迁移到 React Router 的 Remix 用户,@remix-run/cloudflare-pages 中的所有导出现在都为 @react-router/cloudflare 包中的 React Router 用户提供。不再有单独的 Cloudflare Pages 包。(#11801)
  • @react-router/cloudflare - @remix-run/cloudflare-workers 包已被弃用。迁移到 React Router 的 Remix 用户应直接使用 @react-router/cloudflare 包。有关如何在 Cloudflare Workers 上下文中使用 @react-router/cloudflare 的指南,请参阅 Cloudflare Workers 模板。(#11801)
  • @react-router/dev - 对于迁移到 React Router 的 Remix 用户,vitePlugincloudflareDevProxyVitePlugin 导出已重命名并移动。(#11904)
  • @react-router/dev - 对于迁移到 React Router 且使用 Vite 插件的 buildEnd 钩子的 Remix 用户,解析后的 reactRouterConfig 对象不再包含 publicPath 属性,因为这属于 Vite,而不是 React Router (#11575)
  • @react-router/dev - 对于迁移到 React Router 的 Remix 用户,Vite 插件的 manifest 选项已被移除 (#11573)
  • @react-router/dev - 将默认 isbot 版本更新为 v5,并放弃对 isbot@3 的支持 (#11770)
    • 如果您在 package.json 中有 isbot@4isbot@5
      • 您无需进行任何更改
    • 如果您在 package.json 中有 isbot@3 并且您的 repo 中有自己的 entry.server.tsx 文件
      • 您无需进行任何更改
      • 您可以独立于 React Router v7 升级升级到 isbot@5
    • 如果您在 package.json 中有 isbot@3 并且您的 repo 中没有自己的 entry.server.tsx 文件
      • 您正在使用 React Router v7 提供的内部默认条目,并且您需要在您的 package.json 中升级到 isbot@5
  • @react-router/dev - 对于迁移到 React Router 的 Remix 用户,Vite 清单(即 .vite/manifest.json)现在写入每个构建子目录中,例如 build/client/.vite/manifest.jsonbuild/server/.vite/manifest.json,而不是 build/.vite/client-manifest.jsonbuild/.vite/server-manifest.json。这意味着构建输出现在更接近您对典型 Vite 项目的期望。(#11573)
    • 最初,Remix Vite 插件将所有 Vite 清单移动到根级别的 build/.vite 目录,以避免在生产环境中意外提供它们,特别是来自客户端构建。后来,通过额外的逻辑改进了这一点,该逻辑在构建过程结束时删除了这些 Vite 清单文件,除非在应用程序的 Vite 配置中启用了 Vite 的 build.manifest。这大大降低了在生产环境中意外提供 Vite 清单的风险,因为它们仅在明确要求时才存在。因此,我们现在可以假设用户将知道他们需要自己管理这些附加文件,并且 React Router 可以安全地生成更标准的 Vite 构建输出。

小版本更新

  • react-router - 作为路由组件导出 props 的 Params、加载器数据和 action 数据 (#11961)
  • react-router - 添加路由模块类型生成 (#12019)
  • react-router - 移除重复的 RouterProvider 实现 (#11679)
  • react-router - 稳定 unstable_dataStrategy (#11969)
  • react-router - 稳定 unstable_patchRoutesOnNavigation (#11970)
  • react-router - 在使用 Remix SSR 时,为 Link/NavLink 添加预取支持 (#11402)
  • react-router - 增强 ScrollRestoration,使其可以在 SSR 文档加载时正确恢复 (#11401)
  • @react-router/dev - 在 React Router vite 插件中添加对 prerender 配置的支持,以支持现有的 SSG 用例 (#11539)
  • @react-router/dev - 移除与 Single Fetch 异步 hydration 方法不兼容的内部 entry.server.spa.tsx 实现 (#11681)
  • @react-router/serve: 更新 express.static 配置以支持新的 prerender API (#11547)
    • build/client/assets 文件夹中的资源与以前一样提供,具有 1 年不可变的 Cache-Control 标头
    • 资产外部的静态文件(例如预渲染的 .html.data 文件)不使用特定的 Cache-Control 标头提供
    • .data 文件以 Content-Type: text/x-turbo 提供
      • 由于某种原因,当通过 express.static 添加此标头时,它似乎还会向 .data 文件添加 Cache-Control: public, max-age=0

补丁更新

  • substr 替换为 substring (#12080)
  • react-router - 修复了从使用 data() 返回的加载器/action 的重定向 (#12021)
  • @react-router/dev - 为资源路由启用预渲染 (#12200)
  • @react-router/dev - 解析相对于扁平输出文件结构的配置目录 (#12187)

按包变更

完整更新日志: v6.28.0...v7.0.0

React Router v6 版本

v6.29.0

日期:2025-01-30

小版本更新

  • 提供请求 signal 作为 patchRoutesOnNavigation 的参数 (#12900)
    • 这可以用于中止任何清单获取,如果正在进行的导航/fetcher 被中止

补丁更新

  • 不要在生产构建中记录 v7 弃用警告 (#12794)
  • 在抛出 data() 结果时正确冒泡标头 (#12845)
  • 通过在可能的情况下跳过冗余的 matchRoutes 调用来优化路由匹配 (#12169)
  • 从 fetcher 调用的 patchRoutesOnNavigation path 参数中剥离搜索参数 (#12899)

完整更新日志: v6.28.2...v6.29.0

v6.28.2

日期:2025-01-16

补丁更新

  • 修复了在未选择加入 future.v7_fetcherPersist 时手动 fetcher key 的使用问题 (#12674)
  • 修复了 fetcher 卸载时数据层中 fetcher 数据清理的问题 (#12674)

完整更新日志: v6.28.1...v6.28.2

v6.28.1

日期:2024-12-20

补丁更新

  • 允许用户通过将标志设置为 false 来选择退出 v7 弃用警告 (#12441)

完整更新日志: v6.28.0...v6.28.1

v6.28.0

日期:2024-11-06

变更内容

  • 为了准备 v7,我们为尚未选择加入的任何未来标志添加了弃用警告。请使用这些标志来更好地为最终升级到 v7 做准备。

小版本更新

  • 记录 v7 标志的弃用警告 (#11750)
    • json/defer 添加弃用警告,赞成返回原始对象
      • 这些方法将在 React Router v7 中移除

补丁更新

  • 更新新网站结构的 JSDoc URL(添加 /v6/ 段)(#12141)

完整更新日志: v6.27.0...v6.28.0

v6.27.0

日期:2024-10-11

变更内容

稳定的 API

此版本稳定了一系列 “不稳定” 的 API,为 即将发布 的 React Router v7 版本做准备(更多信息请参阅 这些 文章

  • unstable_dataStrategydataStrategy (createBrowserRouter 及其友元) (文档)
  • unstable_patchRoutesOnNavigationpatchRoutesOnNavigation (createBrowserRouter 及其友元) (文档)
  • unstable_flushSyncflushSync (useSubmit, fetcher.load, fetcher.submit) (文档)
  • unstable_viewTransitionviewTransition (<Link>, <Form>, useNavigate, useSubmit) (文档)

次要变更

  • 稳定了导航和 fetcher 的 unstable_flushSync 选项 (#11989)
  • 稳定了导航的 unstable_viewTransition 选项和对应的 unstable_useViewTransitionState hook (#11989)
  • 稳定了 unstable_dataStrategy (#11974)
  • 稳定了 unstable_patchRoutesOnNavigation (#11973)
    • 为了方便,添加了新的 PatchRoutesOnNavigationFunctionArgs 类型 (#11967)

补丁变更

  • 修复了提交到当前上下文路由(带有索引子路由的父路由)时,如果之前提交已存在 ?index 参数的 bug (#12003)
  • 修复了 useFormAction 的 bug - 当移除 ?index 参数时,它不会保留其他非 Remix 的 index 参数 (#12003)
  • 修复了 fetcher 在并发 fetch 期间通过重定向无法持久化 preventScrollReset 的 bug (#11999)
  • 避免了由于背靠背的重新验证调用导致 fetcher 中止时出现不必要的 console.error (#12050)
  • 修复了在使用错误进行 hydration 时 partialHydration 的 bug (#12070)
  • 移除了内部缓存,以修复中断的 patchRoutesOnNavigation 调用问题 (#12055)
    • ⚠️ 如果您依赖于 unstable_ API 中的此行为,则这可能是一个破坏性更改
    • 我们曾经在内部缓存正在进行的 patchRoutesOnNavigation 调用,以便具有相同开始/结束的多次导航仅执行一次该函数并使用相同的 promise
    • 但是,这种方法与 patch 在导航中断时短路(且 request.signal 中止)相矛盾,因为第一次调用的 patch 将不会执行任何操作
    • 此缓存还对有效的缓存键可能是什么做出了一些假设 - 并且忽略了可能发生的任何其他应用程序状态更改
    • 因此,缓存已被移除,因为在大多数情况下,对异步路由的类似 import() 的重复调用已经自动缓存 - 如果没有,用户也很容易在用户空间中实现此缓存
  • unstable_patchRoutesOnNavigation 中移除了内部 discoveredRoutes FIFO 队列 (#11977)
    • ⚠️ 如果您依赖于 unstable_ API 中的此行为,则这可能是一个破坏性更改
    • 这最初是作为一种优化实现的,但事实证明它有点过于限制
    • 如果您需要此优化,则可以在 patchRoutesOnNavigation 内部实现自己的缓存
  • 修复了 PatchRoutesOnNavigationFunctionpatch 方法中 RouteObject 的类型,使其不再期望传递给 patch 的不可知的路由对象 (#11967)
  • 将从 patchRoutesOnNavigation 抛出的错误直接暴露给 useRouteError,而不是将它们包装在 400 ErrorResponse 实例中 (#12111)

完整变更日志: v6.26.2...v6.27.0

v6.26.2

日期:2024-09-09

补丁变更

  • 更新了 unstable_dataStrategy API,以允许更高级的实现 (#11943)
    • ⚠️ 如果您已经采用了 unstable_dataStrategy,请仔细查看,因为这包括对此 API 的破坏性更改
    • unstable_HandlerResult 重命名为 unstable_DataStrategyResult
    • unstable_dataStrategy 的返回签名从 unstable_DataStrategyResult[] 的并行数组(与 matches 并行)更改为 routeId => unstable_DataStrategyResult 的键/值对象
      • 这允许对重新验证行为进行更高级的控制,因为您可以选择加入或退出重新验证默认情况下可能未重新验证的数据(通过 match.shouldLoad
    • 您现在应该从您的 handlerOverride 返回/抛出一个结果,而不是返回 DataStrategyResult
      • 来自您的 handlerOverride 的返回值(或抛出的错误)将被包装到 DataStrategyResult 中,并从 match.resolve 返回
      • 因此,如果您将 match.resolve() 的结果聚合到最终结果对象中,则您不应该需要考虑 DataStrategyResult 类型
      • 如果您正在从您的 handlerOverride 中手动填充您的结果对象,那么您将需要分配一个 DataStrategyResult 作为值,以便 React Router 知道它是成功执行还是错误(有关详细信息,请参阅文档中的示例)
    • unstable_dataStrategy 添加了一个新的 fetcherKey 参数,以区分导航和 fetcher 调用
  • 通过重定向保留选择加入的视图过渡 (#11925)
  • 通过路由器重新验证调用保留待处理的视图过渡 (#11917)
  • 修复了快速/同步调用 blocker.proceed 时 blocker 的使用问题 (#11930)

完整变更日志: v6.26.1...v6.26.2

v6.26.1

日期:2024-08-15

补丁变更

  • unstable_patchRoutesOnMiss 重命名为 unstable_patchRoutesOnNavigation 以匹配新的行为 (#11888)
  • 更新了 unstable_patchRoutesOnNavigation 逻辑,以便在动态参数或 splat 段匹配路由时调用该方法,以防存在我们尚未发现的更高评分的静态路由 (#11883)
    • 我们现在还利用了先前路径的内部 FIFO 队列,我们已经针对这些路径调用了 unstable_patchRoutesOnNavigation,以便我们不会在后续导航到同一路径时重新调用

完整变更日志: v6.26.0...v6.26.1

v6.26.0

日期:2024-08-01

次要变更

  • redirect(url, init?) 添加了一个新的 replace(url, init?) 替代方案,该方案在客户端导航重定向时执行 history.replaceState 而不是 history.pushState (#11811)
  • 为 Remix Single Fetch 添加了一个新的 unstable_data() API (#11836)
    • 此 API 不适用于在 React Router SPA 应用程序中直接使用
    • 它主要用于 createStaticHandler.query(),以允许 loader/action 返回任意数据以及自定义 status/headers,而无需强制将数据序列化为 Response 实例
    • 这允许通过 unstable_dataStrategy 进行更高级的序列化策略,例如在 Remix Single Fetch 中通过 turbo-stream 进行序列化
    • ⚠️ 这从 HandlerResult 中移除了 status 字段
      • 如果您需要从 unstable_dataStrategy 返回特定的 status,您应该改为通过 unstable_data() 进行操作

补丁变更

  • 修复了中断的 fetcher 的内部清理,以避免导航时出现无效的重新验证 (#11839)
  • 修复了使用 future.v7_partialHydration 以及 unstable_patchRoutesOnMiss 时的初始 hydration 行为 (#11838)
    • 在初始 hydration 期间,router.state.matches 现在将包含任何部分匹配项,以便我们可以渲染祖先 HydrateFallback 组件

完整变更日志: v6.25.1...v6.26.0

v6.25.1

日期:2024-07-17

补丁变更

  • 记忆化了一些 RouterProvider 内部组件以减少不必要的重新渲染 (#11803)

完整变更日志: v6.25.0...v6.25.1

v6.25.0

日期:2024-07-16

变更内容

稳定了 v7_skipActionErrorRevalidation

此版本稳定了 future.unstable_skipActionErrorRevalidation 标志,使其成为 future.v7_skipActionErrorRevalidation,为即将到来的 React Router v7 版本做准备。

  • 启用此标志后,返回/抛出 4xx/5xx Response 的 action 默认情况下不会触发重新验证
  • 这也将 shouldRevalidateunstable_actionStatus 参数稳定为 actionStatus

次要变更

  • future.unstable_skipActionErrorRevalidation 稳定为 future.v7_skipActionErrorRevalidation (#11769)

补丁变更

  • 修复了回归问题,并正确解码 useMatch 内部的路径,以便 matches/params 反映解码后的参数 (#11789)
  • 修复了从 unstable_patchRoutesOnMiss 抛出的错误的冒泡问题 (#11786)
  • 修复了在 SSR 应用程序中使用 unstable_patchRoutesOnMiss 时,服务器上匹配 splat 路由的 hydration 问题 (#11790)

完整变更日志: v6.24.1...v6.25.0

v6.24.1

日期:2024-07-03

补丁变更

  • 从警告消息中删除了 polyfill.io 引用,因为该域名已售出,并且此后被确定为提供恶意软件 (#11741)
  • 导出 NavLinkRenderProps 类型,以便更轻松地键入自定义 NavLink 回调 (#11553)
  • 当使用 future.v7_relativeSplatPath 时,正确解析无路径路由的子路由中 splat 路由中的相对路径 (#11633)
  • 战争迷雾(不稳定):在路由修补期间触发新的 router.routes 标识/重排 (#11740)
  • 战争迷雾(不稳定):修复 splat 路由匹配时的初始匹配 (#11759)

完整变更日志: v6.24.0...v6.24.1

v6.24.0

日期:2024-06-24

变更内容

延迟路由发现(又名“战争迷雾”)

我们非常激动地在 v6.24.0 中发布用于“延迟路由发现”的新 API!有关背景信息,请查看原始 RFCtl;dr; 自从我们在 v6.4 中通过 <RouterProvider> 引入数据 API 以来,我们一直有点失望,其中一个权衡是缺乏与我们在 <BrowserRouter>/<Routes> 应用程序中拥有的引人注目的代码拆分故事。我们在 v6.9.0 中通过 route.lazy 向改进这个故事迈出了一小步,但在 v6.24.0 中,我们已经走完了剩下的路。

借助“战争迷雾”,您现在可以通过传递给 createBrowserRouter(及其内存/哈希对应物)的新 unstable_patchRoutesOnMiss 选项,延迟加载部分路由树。这为您提供了一种在 React Router 无法匹配给定路径的位置挂钩并在导航(或 fetcher 调用)期间将新路由修补到路由树中的方法。

这是一个非常小的示例,但有关更多信息和用例,请参阅 文档

const router = createBrowserRouter(
  [
    {
      id: "root",
      path: "/",
      Component: RootComponent,
    },
  ],
  {
    async unstable_patchRoutesOnMiss({ path, patch }) {
      if (path === "/a") {
        // Load the `a` route (`{ path: 'a', Component: A }`)
        let route = await getARoute();
        // Patch the `a` route in as a new child of the `root` route
        patch("root", [route]);
      }
    },
  }
);

次要变更

  • 添加了对延迟路由发现(又名“战争迷雾”)的支持 (#11626)

补丁变更

  • 修复了 fetcher.submit 类型 - 移除了不正确的 navigate/fetcherKey/unstable_viewTransition 选项,因为它们仅与 useSubmit 相关 (#11631)
  • 允许将 falsy location.state 值传递给 <StaticRouter> (#11495)

完整变更日志: v6.23.1...v6.24.0

v6.23.1

日期:2024-05-10

补丁变更

  • 允许通过 <Await> 解析 undefined (#11513)
  • 在检查 document.startViewTransition 可用性时,添加了防御性的 document 检查 (#11544)
  • react-router-dom/server 导入改回 react-router-dom 而不是 index.ts (#11514)
  • @remix-run/router - 在 staticHandler.queryRoute 上支持 unstable_dataStrategy (#11515)

完整变更日志: v6.23.0...v6.23.1

v6.23.0

日期:2024-04-23

变更内容

数据策略(不稳定)

新的 unstable_dataStrategy API 是一个底层 API,专为高级用例而设计,在这些用例中,您需要控制 loader/action 函数的数据策略。默认实现是今天的行为,并行获取所有 loader,但此选项允许用户实现更高级的数据流,包括 Remix “Single Fetch”、用户空间中间件/上下文 API、自动 loader 缓存等等。有关更多信息,请参阅 文档

注意: 这是一个底层 API,旨在用于高级用例。这会覆盖 React Router 内部对 loader/action 执行的处理,如果操作不当,将破坏您的应用程序代码。请谨慎使用并执行适当的测试。

跳过 Action 错误重新验证(不稳定)

目前,所有活动的 loader 都会在任何 action 提交后重新验证,无论 action 结果如何。但是,在大多数情况下,来自 action4xx/5xx 响应意味着实际上没有数据被更改,并且重新验证是不必要的。我们引入了一个新的 future.unstable_skipActionErrorRevalidation 标志,该标志更改了此处的行为,我们计划使其成为未来 React Router 版本中的默认设置。

启用此标志后,返回/抛出 4xx/5xx 响应状态的 action 将不再自动重新验证。如果您需要在启用此标志的 4xx/5xx 结果后重新验证,您仍然可以通过从 shouldRevalidate 返回 true 来实现 - 现在 shouldRevalidate 还接收一个新的 unstable_actionStatus 参数以及 actionResult,因此您可以根据 action 响应的状态做出决策,而无需将其编码到 action 数据中。

次要变更

  • 添加了一个新的 unstable_dataStrategy 配置选项 (#11098, #11377)
  • @remix-run/router - 添加了一个新的 future.unstable_skipActionRevalidation future 标志 (#11098)
  • @remix-run/router - SSR: 为 staticHandler.query 方法添加了一个新的 skipLoaderErrorBubbling 选项,以禁用静态处理程序的错误冒泡,以便在 Remix 的 Single Fetch 实现中使用 (#11098, (#11377))

完整变更日志: v6.22.3...v6.23.0

v6.22.3

日期:2024-03-07

补丁变更

  • 修复了 future.v7_partialHydration 的一个 bug,如果 SSR loader 错误冒泡到父边界,则该 bug 会在 hydration 时重新运行边界下方的 loader (#11324)
  • 修复了 future.v7_partialHydration 的一个 bug,如果路由没有 loader,则该 bug 会将路由器视为未初始化状态 (#11325)

完整变更日志: v6.22.2...v6.22.3

v6.22.2

日期:2024-02-28

补丁变更

  • 在部分 hydration 运行期间保留了 hydrated 错误 (#11305)

完整变更日志: v6.22.1...v6.22.2

v6.22.1

日期:2024-02-16

补丁变更

  • 修复了预编码动态参数值的编码/解码问题 (#11199)

完整变更日志: v6.22.0...v6.22.1

v6.22.0

日期:2024-02-01

变更内容

Core Web Vitals 技术报告标志

2021 年,HTTP Archive 启动了 Core Web Vitals 技术报告仪表板

通过将 Chrome 用户体验报告 26 (CrUX) 数据集中的真实用户体验与 HTTP Archive 30 中的 Web 技术检测相结合,我们可以了解 CMS 平台或 JavaScript 框架选择等架构决策如何在网站的 CWV 性能中发挥作用。

他们使用名为 wappalyzer 的工具,通过查找某些脚本、全局 JS 变量或其他识别特征来识别给定网站正在使用的技术。例如,对于 Remix 应用程序,他们 查找全局 __remixContext 变量来识别网站是否正在使用 Remix。

我们注意到 React Router 无法可靠地识别,因为没有识别全局方面。他们目前 正在查找名称中带有 react-router 的外部脚本。这将识别从 CDN(如 unpkg)使用 React Router 的站点 - 但它会错过绝大多数从 npm 注册表安装 React Router 并将其捆绑到其 JS 文件中的站点。这导致 React Router 在 Web 上的使用情况 被严重低估

6.22.0 版本开始,使用 react-router-dom 的站点将开始添加 window.__reactRouterVersion 变量,该变量将被设置为 SemVer 主要版本号的字符串值(即,window.__reactRouterVersion = "6";),以便可以正确识别它们。

次要变更

  • 包含用于 CWV 报告检测的 window.__reactRouterVersion (#11222)
  • 添加了 createStaticHandler future.v7_throwAbortReason 标志,以便在请求中止时抛出 request.signal.reason(默认为 DOMException)而不是 Error,例如 new Error("query() call aborted: GET /path") (#11104)
    • 请注意,DOMException 是在 Node v17 中添加的,因此您在 Node 16 及更低版本上不会获得 DOMException

补丁变更

  • 如果传递给 getStaticContextFormError,则尊重 ErrorResponse 状态代码 (#11213)

完整变更日志: v6.21.3...v6.22.0

v6.21.3

日期:2024-01-18

补丁变更

  • 修复了使用 basenameNavLink isPending 的问题 (#11195)
  • Blocker/BlockerFunction 类型中移除了剩余的 unstable_ 前缀 (#11187)

完整变更日志: v6.21.2...v6.21.3

v6.21.2

日期:2024-01-11

补丁变更

  • 在可用时,利用 useId 作为内部 fetcher 键 (#11166)
  • 修复了动态参数名称中未拾取破折号的 bug (#11160)
  • 不要尝试反序列化空的 JSON 响应 (#11164)

完整变更日志: v6.21.1...v6.21.2

v6.21.1

日期:2023-12-21

补丁变更

  • 修复了 route.lazy 在指定 v7_partialHydration 时在初始 SPA 加载时无法正常工作的 bug (#11121)
  • 修复了阻止为在 submitting 阶段卸载的持久化 fetcher 发生重新验证的 bug (#11102)
  • resolveTo 中重复数据删除相对路径逻辑 (#11097)

完整变更日志: v6.21.0...v6.21.1

v6.21.0

日期:2023-12-13

变更内容

future.v7_relativeSplatPath

我们在 6.19.0 中修复了一个 splat 路由路径解析 bug,但后来确定大量应用程序依赖于错误的行为,因此我们在 6.20.1 中恢复了该修复(请参阅 #10983, #11052, #11078)。

错误的行为是,在 splat 路由内部解析相对路径时的默认行为将忽略当前路由路径的任何 splat (*) 部分。启用 future 标志后,splat 部分将包含在 splat 路由内的相对路径逻辑中。

有关更多信息,请参阅 useResolvedPath 文档和/或 详细的变更日志条目

部分 Hydration

我们为 @remix-run/router 添加了一个新的 future.v7_partialHydration future 标志,该标志在服务器端渲染时启用数据路由器的部分 hydration。这允许您提供 hydrationData.loaderData,其中包含某些初始匹配路由加载器的值,但并非全部。启用此标志后,路由器将在 router.initialize() 期间为没有 hydration loader 数据的路由调用 loader 函数,并且它将在执行未 hydration 的路由时渲染到最深层提供的 HydrateFallback(直到第一个没有 hydration 数据的路由)。(#11033)

次要变更

  • 添加了一个新的 future.v7_relativeSplatPath 标志,以实现对 splat 路由内部相对路由的破坏性 bug 修复。 (#11087)
  • 添加了一个新的 future.v7_partialHydration future 标志,该标志在服务器端渲染时启用数据路由器的部分 hydration (#11033)

补丁变更

  • 正确处理 ErrorBoundary 中的 falsy 错误值 (#11071)
  • 捕获并冒泡尝试从 loader/action 函数解包响应时抛出的错误 (#11061)
  • 修复了在匹配路由之外渲染 Link/NavLink 时的 relative="path" 问题 (#11062)

完整变更日志: v6.20.1...v6.21.0

v6.20.1

日期:2023-12-01

补丁变更

  • 由于大量应用程序依赖于错误的行为,因此恢复了 splat 路由的 useResolvedPath 修复(请参阅 #11052) (#11078)
    • 我们计划在下一个次要版本中在 future 标志后面重新引入此修复(请参阅 此评论
    • 此修复包含在 6.19.06.20.0 版本中。如果您是从 6.18.0 或更早版本升级,您将不会受到此修复的影响。

完整变更日志: v6.20.0...v6.20.1

v6.20.0

日期:2023-11-22

[!WARNING] 请使用 6.20.1 或更高版本,而不是 6.20.0。我们发现大量应用程序依赖于此版本中修复的错误行为 (#11045)。我们在 6.20.1 中恢复了该修复,并将在后续版本中在 future 标志后面重新引入它。有关更多详细信息,请参阅 #11052

次要变更

  • 从公共 API 导出 PathParam 类型 (#10719)

补丁变更

  • 当启用 v7_fetcherPersist 时,不要重新验证已卸载的 fetcher (#11044)
  • 修复了 splat 路由中 resolveTo 路径解析的 bug (#11045)
    • 这是对 #10983 的跟进,以处理使用 getPathContributingMatches 的其他一些代码路径
    • 由于我们不再需要在 react-router/react-router-dom 层中使用 UNSAFE_getPathContributingMatches,因此从 @remix-run/router 中移除了 UNSAFE_getPathContributingMatches 导出

完整变更日志: v6.19.0...v6.20.0

v6.19.0

日期:2023-11-16

[!WARNING] 请使用 6.20.1 或更高版本,而不是 6.19.0。我们发现大量应用程序依赖于此版本中修复的错误行为 (#10983)。我们在 6.20.1 中恢复了该修复,并将在后续版本中在 future 标志后面重新引入它。有关更多详细信息,请参阅 #11052

变更内容

unstable_flushSync API

此版本为命令式 API (useSubmit, useNavigate, fetcher.submit, fetcher.load) 带来了一个新的 unstable_flushSync 选项,以允许用户选择加入同步 DOM 更新以实现待处理/乐观 UI。

function handleClick() {
  submit(data, { flushSync: true });
  // Everything is flushed to the DOM so you can focus/scroll to your pending/optimistic UI
  setFocusAndOrScrollToNewlyAddedThing();
}

次要变更

  • unstable_flushSync 选项添加到 useNavigate/useSubmit/fetcher.load/fetcher.submit,以便选择退出 React.startTransition 并选择加入 ReactDOM.flushSync 以进行状态更新 (#11005)
  • useBlocker hook 中移除了 unstable_ 前缀,因为它已经使用了足够长的时间,我们对其 API 充满信心 (#10991)
    • 由于浏览器处理 window.confirm 的方式存在差异,这会阻止 React Router 保证一致/正确的行为,因此我们不计划从 unstable_usePrompt 中移除前缀

补丁变更

  • 修复了 useActionData,使其返回正确的上下文 action 数据,而不是树中的任何 action 数据 (#11023)

  • 修复了 useResolvedPath 中的 bug,该 bug 会导致 splat 路由中的 useResolvedPath(".") 丢失 URL 路径的 splat 部分。 (#10983)

    • ⚠️ 这修复了一个相当长期的 bug,特别是对于 splat 路由内部的 "." 路径,该路径错误地丢弃了 URL 的 splat 部分。如果您在应用程序中的 splat 路由内部通过 "." 进行相对路由,则应仔细检查您的逻辑是否不依赖于此错误的行为,并进行相应更新。
  • 修复了在保持挂载状态的 useFetcher 中更改 fetcher key 未被拾取的问题 (#11009)

  • 修复了 useFormAction,它错误地从子路由 action 提交中继承了 ?index 查询参数 (#11025)

  • 修复了 NavLink active 逻辑,当 to 位置具有尾部斜杠时 (#10734)

  • 修复了类型,以便 unstable_usePrompt 除了 boolean 之外,还可以接受 BlockerFunction (#10991)

  • 修复了 relative="path" 错误,该错误导致相对路径计算从完整的 location pathname 开始,而不是从当前上下文路由 pathname 开始。(<#11006>)

    <Route path="/a">
      <Route path="/b" element={<Component />}>
        <Route path="/c" />
      </Route>
    </Route>;
    
    function Component() {
      return (
        <>
          {/* This is now correctly relative to /a/b, not /a/b/c */}
          <Link to=".." relative="path" />
          <Outlet />
        </>
      );
    }
    

完整更新日志: 6.18.0...6.19.0

v6.18.0

日期: 2023-10-31

更新内容

新的 Fetcher API

根据此 RFC,我们引入了一些新的 API,使您可以更精细地控制 fetcher 的行为。

  • 您现在可以通过 useFetcher({ key: string }) 指定您自己的 fetcher 标识符,这允许您从应用程序中的不同组件访问相同的 fetcher 实例,而无需逐层传递 props
  • Fetcher 键现在在从 useFetchers 返回的 fetcher 上公开,以便可以通过 key 查找它们
  • FormuseSubmit 现在支持可选的 navigate/fetcherKey props/params,以允许在后台启动 fetcher 提交,并可选择用户指定的 key
    • <Form method="post" navigate={false} fetcherKey="my-key">
    • submit(data, { method: "post", navigate: false, fetcherKey: "my-key" })
    • 以这种方式调用 fetcher 是短暂且无状态的
    • 如果您需要访问其中一个 fetcher 的状态,您将需要利用 useFetchers()useFetcher({ key }) 在其他地方查找它

持久化 Future Flag (future.v7_fetcherPersist)

根据与上述相同的 RFC,我们引入了一个新的 future.v7_fetcherPersist 标志,允许您选择加入新的 fetcher 持久化/清理行为。Fetcher 不会在卸载时立即清理,而是会持续存在,直到它们返回到 idle 状态。这使得在原始 fetcher 需要卸载的情况下,待处理/乐观 UI 更加 容易实现。

  • 这有点像一个长期存在的 bug 修复,因为 useFetchers() API 始终应该只反映待处理/乐观 UI 的 正在进行中 的 fetcher 信息 -- 它不打算反映 fetcher 数据或在 fetcher 返回到 idle 状态后保留 fetcher
  • 请密切关注选择加入此标志时的以下特定行为更改,并检查您的应用程序的兼容性
    • 在仍然挂载时 完成的 Fetcher 将不再出现在完成后的 useFetchers() 中 - 它们在那里没有用处,因为您可以通过 useFetcher().data 访问数据
    • 先前在进行中 卸载的 Fetcher 不会立即中止,而是在它们返回到 idle 状态后清理
      • 它们将在进行中时通过 useFetchers 保持公开,以便您仍然可以在卸载后访问待处理/乐观数据
      • 如果 fetcher 完成时不再挂载,则它的结果将不会被后处理 - 例如,不会跟随重定向,错误也不会在 UI 中冒泡
      • 但是,如果 fetcher 使用相同的 key 在树中的其他位置重新挂载,则即使原始 fetcher 已卸载,其结果也将被处理

次要更改

  • 添加 fetcher key API 和 navigate=false 选项 (<#10960>)
  • 添加 future.v7_fetcherPersist 标志 (<#10962>)
  • matchPath 中添加对可选路径段的支持 (<#10768>)

补丁更新

  • 修复 BrowserRouterHashRouterMemoryRouter 上的 future prop,使其接受 Partial<FutureConfig> 而不是要求包含所有标志 (<#10962>)
  • 修复 router.getFetcher/router.deleteFetcher 类型定义,它们错误地将 key 指定为可选参数 (<#10960>)

完整更新日志: 6.17.0...6.18.0

v6.17.0

日期: 2023-10-16

更新内容

视图过渡 🚀

我们很高兴在 React Router 中发布对 View Transitions API 的实验性支持!您现在可以触发导航 DOM 更新以包裹在 document.startViewTransition 中,从而在您的应用程序中为 SPA 导航启用 CSS 动画过渡效果。

在您的 React Router 应用程序中启用视图过渡的最简单方法是通过新的 <Link unstable_viewTransition> prop。这将导致导航 DOM 更新包裹在 document.startViewTransition 中,这将为 DOM 更新启用过渡效果。在没有任何额外的 CSS 样式的情况下,您将获得页面基本的交叉淡入淡出动画。

如果您需要为动画应用更精细的样式,您可以利用 unstable_useViewTransitionState hook,它会告诉您过渡何时正在进行中,您可以使用它来应用类或样式

function ImageLink(to, src, alt) {
  const isTransitioning = unstable_useViewTransitionState(to);
  return (
    <Link to={to} unstable_viewTransition>
      <img
        src={src}
        alt={alt}
        style={{
          viewTransitionName: isTransitioning ? "image-expand" : "",
        }}
      />
    </Link>
  );
}

您还可以使用 <NavLink unstable_viewTransition> 简写,它将为您管理 hook 的使用,并在过渡期间自动向 <a> 添加 transitioning

a.transitioning img {
  view-transition-name: "image-expand";
}
<NavLink to={to} unstable_viewTransition>
  <img src={src} alt={alt} />
</NavLink>

有关视图过渡的用法示例,请查看 我们的 fork,它是令人惊叹的 Astro Records 演示。

有关使用 View Transitions API 的更多信息,请参阅 Google Chrome 团队的 使用 View Transitions API 实现平滑简单的过渡 指南。

次要更改

  • 添加对视图过渡的支持 (<#10916>)

补丁更新

  • sessionStorage 不可用时,在 ScrollRestoration 中记录警告并优雅地失败 (<#10848>)
  • 修复 RouterProvider future prop 类型为 Partial<FutureConfig>,以便不必指定所有标志 (<#10900>)
  • 允许 404 检测利用根路由错误边界,如果路径包含 URL 段 (<#10852>)
  • 修复 ErrorResponse 类型以避免泄漏内部字段 (<#10876>)

完整更新日志: 6.16.0...6.17.0

v6.16.0

日期: 2023-09-13

次要更改

  • 为了在未来朝着更严格的 TypeScript 支持方向发展,我们的目标是在为用户提供的数据公开的类型定义中,用 unknown 替换当前 any 的用法。为了在 Remix v2 中实现这一点,而不会在 React Router v6 中引入破坏性更改,我们向许多共享类型添加了泛型。这些在 React Router 中继续默认为 any,并在 Remix 中被 unknown 覆盖。在 React Router v7 中,我们计划将这些更改为 unknown,作为一项破坏性更改。(<#10843>)
    • Location 现在接受 location.state 值的泛型
    • ActionFunctionArgs/ActionFunction/LoaderFunctionArgs/LoaderFunction 现在接受 context 参数的泛型 (仅在通过 createStaticHandler 的 SSR 用法中使用)
    • useMatches 的返回类型 (现在导出为 UIMatch) 接受 match.datamatch.handle 的泛型 - 这两者都已设置为 unknown
  • @private 类导出 ErrorResponse 移动到 UNSAFE_ErrorResponseImpl 导出,因为它是一个实现细节,并且用户端不应构造 ErrorResponse 实例。这使我们能够自由地导出一个 type ErrorResponse,它通过 InstanceType 与该类的实例相关联。用户端代码应始终仅将 ErrorResponse 用作类型,并且应通过 isRouteErrorResponse 进行类型缩小。(<#10811>)
  • 导出 ShouldRevalidateFunctionArgs 接口 (<#10797>)
  • 移除了仅 Remix v1 向后兼容层所需的私有/内部 API,并且在 Remix v2 中不再需要 (_isFetchActionRedirect, _hasFetcherDoneAnything) (<#10715>)

补丁更新

  • 正确编码服务器渲染中的渲染 URI,以避免 hydration 错误 (<#10769>)
  • 在中止的 query/queryRoute 调用中,向错误消息添加 method/url (<#10793>)
  • 修复 route.lazy 路由上 loader/action 抛出错误的竞争条件 (<#10778>)
  • 修复传递给 shouldRevalidate 的 arguments 对象上的 actionResult 类型 (<#10779>)

完整更新日志: v6.15.0...v6.16.0

v6.15.0

日期: 2023-08-10

次要更改

  • 添加了一个新的 redirectDocument() 函数,允许用户指定来自 loader/action 的重定向应触发文档重新加载 (通过 window.location),而不是尝试通过 React Router 导航到重定向的位置 (<#10705)

补丁更新

  • 确保 useRevalidator 在重新渲染中保持引用稳定,如果重新验证未主动发生 (<#10707>)
  • 确保 hash history 始终在 hash pathname 上包含前导斜杠 (<#10753>)
  • 修复了影响 Firefox 中使用 URLSearchParamsuseSearchParams hook 的 Web 扩展的边缘情况 (<#10620>)
  • 重新排序 unstable_usePrompt 中的 effects,以避免在 prompt 被解除阻止并且同步执行导航时抛出异常 (<#10687, #10718)
  • SSR: 不要在未指定的 actions 的 useFormAction() 中包含 hash,因为它无法在服务器上确定,并会导致 hydration 问题 (<#10758>)
  • SSR: 修复了 queryRoute 中未始终识别抛出的 Response 实例的问题 (<#10717>)
  • react-router-native: 将 @ungap/url-search-params 依赖项从 ^0.1.4 更新到 ^0.2.2 (<#10590>)

完整更新日志: v6.14.2...v6.15.0

v6.14.2

日期: 2023-07-17

补丁更新

  • 添加缺少的 <Form state> prop 以在提交导航时填充 history.state (<#10630>)
  • 如果 defer promise 解析/拒绝为 undefined,则触发错误,以便与 loaders 和 actions 的行为匹配,后者必须返回值或 null (<#10690>)
  • 正确处理被正常导航中断的 fetcher 重定向 (<#10674>)
  • 初始加载 fetcher 不应在 GET 导航时自动重新验证 (<#10688>)
  • 通过 <ScrollRestoration> 模拟 hash 滚动时,正确解码元素 id (<#10682>)
  • Typescript: 增强 Route.lazy 的返回类型,以禁止返回空对象 (<#10634>)
  • SSR: 支持 Error 子类(例如 ReferenceError/TypeError)的正确 hydration (<#10633>)

完整更新日志: v6.14.1...v6.14.2

v6.14.1

日期: 2023-06-30

补丁更新

  • 修复与不稳定的 blocker 函数一起使用时 unstable_useBlocker 中的循环 (<#10652>)
  • 修复后续导航中重用 blockers 的问题 (<#10656>)
  • 更新的依赖项
    • @remix-run/router@1.7.1

完整更新日志: v6.14.0...v6.14.1

v6.14.0

日期: 2023-06-23

更新内容

JSON/文本提交

6.14.0 添加了对通过 useSubmit/fetcher.submit 进行 JSON 和文本提交的支持,因为如果您在客户端 SPA 中工作,则不必总是序列化为 FormData。要选择加入这些编码,您只需指定正确的 formEncType

选择加入 application/json 编码

function Component() {
  let navigation = useNavigation();
  let submit = useSubmit();
  submit({ key: "value" }, { method: "post", encType: "application/json" });
  // navigation.formEncType => "application/json"
  // navigation.json        => { key: "value" }
}

async function action({ request }) {
  // request.headers.get("Content-Type") => "application/json"
  // await request.json()                => { key: "value" }
}

选择加入 text/plain 编码

function Component() {
  let navigation = useNavigation();
  let submit = useSubmit();
  submit("Text submission", { method: "post", encType: "text/plain" });
  // navigation.formEncType => "text/plain"
  // navigation.text        => "Text submission"
}

async function action({ request }) {
  // request.headers.get("Content-Type") => "text/plain"
  // await request.text()                => "Text submission"
}

⚠️ v7 中的默认行为将更改

请注意,为避免破坏性更改,默认行为仍会将简单的键/值 JSON 对象编码为 FormData 实例

function Component() {
  let navigation = useNavigation();
  let submit = useSubmit();
  submit({ key: "value" }, { method: "post" });
  // navigation.formEncType => "application/x-www-form-urlencoded"
  // navigation.formData    => FormData instance
}

async function action({ request }) {
  // request.headers.get("Content-Type") => "application/x-www-form-urlencoded"
  // await request.formData()            => FormData instance
}

此行为很可能在 v7 中更改,因此最好使用 formEncType: "application/x-www-form-urlencoded"formEncType: "application/json" 显式进行任何 JSON 对象提交,以简化您最终的 v7 迁移路径。

次要更改

  • useSubmit/fetcher.submit 添加对 application/jsontext/plain 编码的支持。为了反映这些附加类型,useNavigation/useFetcher 现在还包含 navigation.json/navigation.textfetcher.json/fetcher.text,其中包括 json/text 提交(如果适用)。(<#10413>)

补丁更新

  • submitter 元素提交表单时,首选内置的 new FormData(form, submitter),而不是现代浏览器(那些支持新的 submitter 参数的浏览器)中以前的手动方法 (<#9865>)
    • 对于不支持它的浏览器,我们继续仅将 submit 按钮的条目附加到末尾,并且我们还添加了对 type="image" 按钮的基本支持
    • 如果开发人员想要对旧版浏览器进行完全符合规范的支持,他们可以使用 formdata-submitter-polyfill
  • 在更新 React Router 状态之前(而不是之后)调用 window.history.pushState/replaceState,以便 window.location 在同步 React 17 渲染期间与 useLocation 匹配 (<#10448)
    • ⚠️ 注意:通常应用程序不应依赖 window.location,并且应尽可能始终引用 useLocation,因为 window.location 不会 100% 同步(由于 popstate 事件、并发模式等)
  • 避免为尚未完成数据加载的 fetcher 调用 shouldRevalidate (<#10623>)
  • 从提供给 <ScrollRestoration getKey>location 中剥离 basename,以匹配 useLocation 行为 (<#10550>)
  • 从提供给 unstable_useBlocker 函数的位置中剥离 basename,以匹配 useLocation 行为 (<#10573>)
  • 修复 StrictMode 中的 unstable_useBlocker 键问题 (<#10573>)
  • 修复传递数值 0 值参数时 generatePath (<#10612>)
  • 修复 React 17 上的 tsc --skipLibCheck:false 问题 (<#10622>)
  • typescript 升级到 5.1 (<#10581>)

完整更新日志: v6.13.0...v6.14.0

v6.13.0

日期: 2023-06-14

更新内容

6.13.0 实际上是一个补丁版本,但在精神上带有一个 SemVer 次要版本升级,因为我们添加了一个新的 future 标志。

future.v7_startTransition

简而言之; 6.13.06.12.0 相同,但是我们将 React.startTransition 的用法移到了选择加入的 future.v7_startTransition future 标志 之后,因为我们发现存在一些应用程序在野外以与 React.startTransition 不兼容的方式使用 Suspense

因此,在 6.13.0 中,默认行为将不再利用 React.startTransition

<BrowserRouter>
  <Routes>{/*...*/}</Routes>
</BrowserRouter>

<RouterProvider router={router} />

如果您希望启用 React.startTransition,请将 future 标志传递给您的 router 组件

<BrowserRouter future={{ v7_startTransition: true }}>
  <Routes>{/*...*/}</Routes>
</BrowserRouter>

<RouterProvider router={router} future={{ v7_startTransition: true }}/>

我们建议大家尽早采用此标志,以便更好地与 React 并发模式兼容,但是如果您遇到问题,您可以继续不使用 React.startTransition,直到 v7。问题通常归结为在渲染周期中创建全新的 promises,因此如果您在选择加入 React.startTransition 时遇到问题,则应将 promise 创建移出渲染周期,或将其放在 useMemo 之后。

次要更改

  • React.startTransition 用法移到 future 标志之后 (<#10596>)

补丁更新

  • 解决生产模式下 webpack/terser React.startTransition 最小化 bug (<#10588>)

完整更新日志: v6.12.1...v6.13.0

v6.12.1

日期: 2023-06-08

[!WARNING] 请使用 6.13.0 或更高版本,而不是 6.12.0/6.12.1。这些版本受到一些 Webpack 构建/最小化问题的困扰,导致生产包中构建失败或最小化代码无效。有关更多详细信息,请参阅 #10569#10579

补丁更新

  • 调整 React.startTransition 的功能检测,以修复 webpack + react 17 编译错误 (<#10569>)

完整更新日志: v6.12.0...v6.12.1

v6.12.0

日期: 2023-06-06

[!WARNING] 请使用 6.13.0 或更高版本,而不是 6.12.0/6.12.1。这些版本受到一些 Webpack 构建/最小化问题的困扰,导致生产包中构建失败或最小化代码无效。有关更多详细信息,请参阅 #10569#10579

更新内容

React.startTransition 支持

6.12.0 中,我们通过将内部路由器状态更新包裹在 React.startTransition 中,添加了对挂起组件的更好支持。这意味着,例如,如果目标路由中的组件之一挂起,并且您没有提供 Suspense 边界来显示 fallback,React 将延迟新 UI 的渲染,并显示旧 UI,直到该异步操作完成。这对于等待图像或 CSS 文件加载等情况可能很有用(从技术上讲,是的,您可以使用它进行数据加载,但我们仍然建议使用 loaders 😀)。有关此用法的快速概述,请查看 Ryan 在 Twitter 上的演示

次要更改

  • 使用 React.startTransition 包裹内部路由器状态更新 (<#10438>)

补丁更新

  • 允许 fetcher 重新验证完成,如果提交 fetcher 被删除 (<#10535>)
  • 当尝试使用不可序列化的状态执行 PUSH 导航时,重新抛出 DOMException (DataCloneError)。(<#10427>)
  • 确保在存在 hash 时发生重新验证 (<#10516>)
  • 升级 jestjsdom (<#10453>)
  • 更新的依赖项

完整更新日志: v6.11.2...v6.12.0

v6.11.2

日期: 2023-05-17

补丁更新

  • 修复后代 <Routes><RouterProvider> 内部的 basename 重复问题 (<#10492>)
  • 修复当存在 hash 时初始数据加载不会启动的 bug (<#10493>)
  • 导出 SetURLSearchParams 类型 (<#10444>)
  • 通过在 _internalSetRoutes 中正确重建新路由和 manifest,修复 Remix HMR 驱动的错误边界 (<#10437>)

完整更新日志: v6.11.1...v6.11.2

v6.11.1

日期: 2023-05-03

补丁更新

  • 修复后代 <Routes> 内的 Component API 的用法 (<#10434>)
  • 修复从 <RouterProvider> 内部的 <Routes> 调用 useNavigate 时的 bug (<#10432>)
  • 修复在使用数据路由器时,在严格模式下 <Navigate> 的用法 (<#10435>)
  • 修复在没有路径的情况下导航时 basename 处理 (<#10433>)
  • “相同 hash” 导航不再重新运行 loaders 以匹配浏览器行为 (即 /path#hash -> /path#hash) (<#10408>)

完整更新日志: v6.11.0...v6.11.1

v6.11.0

日期: 2023-04-28

次要更改

  • useFetcher 中启用 basename 支持 (<#10336>)
    • 如果您之前通过手动预先添加 basename 来解决此问题,那么您将需要从您的 fetcher 调用中删除手动预先添加的 basename (fetcher.load('/basename/route') -> fetcher.load('/route'))
  • 更新的依赖项

补丁更新

  • 当使用 RouterProvider 时,useNavigate/useSubmit/fetcher.submit 现在在位置更改时是稳定的,因为我们可以通过 @remix-run/router 实例处理相对路由,并摆脱我们对 useLocation() 的依赖 (<#10336>)
    • 当使用 BrowserRouter 时,这些 hooks 在位置更改时仍然不稳定,因为它们仍然依赖于 useLocation()
  • Fetcher 不应再在搜索参数更改或路由到相同 URL 时重新验证,并且仅在 action 提交或 router.revalidate 调用时重新验证 (<#10344>)
  • 修复在路由定义上使用 Component 而不是 element 时意外重新渲染的问题 (<#10287>)
  • <Link to="//"> 和其他无效 URL 值上优雅地失败 (<#10367>)
  • 将内部 @remix-run/router 路由器状态同步的 <RouterProvider> 中的 useSyncExternalStore 切换为 useState。我们发现了一些 细微的 bug,其中路由器状态更新在其他正常的 useState 更新之前传播,这可能导致 useEffect 调用中的 foot guns。(<#10377, #10409)
  • 将默认错误边界捕获的 loader/action 错误记录到开发控制台,以便更轻松地评估堆栈跟踪 (<#10286>)
  • 修复当 RouterProvider 错误存在时阻止渲染后代 <Routes> 的 bug (<#10374>)
  • 通过在布局 effect 中设置 activeRef 来修复在渲染周期中检测 useNavigate,允许将 navigate 函数传递给子组件并在那里的 useEffect 中调用 (<#10394>)
  • 允许 useRevalidator() 解决 loader 驱动的错误边界场景 (<#10369>)
  • 增强 LoaderFunction/ActionFunction 返回类型,以防止 undefined 成为有效的返回值 (<#10267>)
  • 确保在对没有 loader 的路由进行 fetcher.load 调用时出现正确的 404 错误 (<#10345>)
  • 解耦重新验证 fetchers 和触发它们的事件之间的 AbortController 用法,这样重新验证 fetcher 的卸载/删除不会影响正在进行的触发导航/重新验证 (<#10271>)

完整更新日志: v6.10.0...v6.11.0

v6.10.0

日期: 2023-03-29

更新内容

我们最近在 Remix 博客上发布了一篇名为 “面向未来地构建您的 Remix 应用程序” 的文章,其中介绍了我们的策略,以确保您的 Remix 和 React Router 应用程序在未来能够顺利升级。React Router 6.10.0 添加了对这些标志(对于数据路由器)的支持,您可以在创建路由器时指定这些标志

const router = createBrowserRouter(routes, {
  future: {
    // specify future flags here
  },
});

您还可以查看文档 此处此处

次要更改

future.v7_normalizeFormMethod

引入的第一个 future 标志是 future.v7_normalizeFormMethod,它将标准化公开的 useNavigation()/useFetcher() formMethod 字段作为大写 HTTP 方法,以与 fetch()(和一些 Remix)行为对齐。(<#10207>)

  • future.v7_normalizeFormMethod 未指定或设置为 false(默认 v6 行为)时,
    • useNavigation().formMethod 是小写
    • useFetcher().formMethod 是小写
  • future.v7_normalizeFormMethod === true
    • useNavigation().formMethod 是大写
    • useFetcher().formMethod 是大写

补丁更新

  • 修复 createStaticHandler 以在路由上检查 ErrorBoundary 以及 errorElement (<#10190>)
  • 修复在 createRoutesFromElements 中使用 Fragments 时的路由 ID 生成 (<#10193>)
  • 如果 fetcher action 重定向,则将 fetcher 提交提供给 shouldRevalidate (<#10208>)
  • 正确处理路由器初始化期间的 lazy() 错误 (<#10201>)
  • 删除 DeferredDatainstanceof 检查,以在 SSR 捆绑场景中对 ESM/CJS 边界具有弹性 (<#10247>)
  • 更新到最新的 @remix-run/web-fetch@4.3.3 (<#10216>)

完整更新日志: v6.9.0...v6.10.0

v6.9.0

日期: 2023-03-10

更新内容

Component/ErrorBoundary 路由属性

React Router 现在支持一种替代方法,将您的路由 elementerrorElement 字段定义为 React 组件,而不是 React 元素。如果您选择,您可以将 React 组件传递给新的 ComponentErrorBoundary 字段。两者之间没有功能差异,因此请使用您喜欢的任何一种方法 😀。您不应同时定义两者,但如果您这样做,Component/ErrorBoundary 将“胜出”

JSON 语法示例

// Both of these work the same:
const elementRoutes = [{
  path: '/',
  element: <Home />,
  errorElement: <HomeError />,
}]

const componentRoutes = [{
  path: '/',
  Component: Home,
  ErrorBoundary: HomeError,
}]

function Home() { ... }
function HomeError() { ... }

JSX 语法示例

// Both of these work the same:
const elementRoutes = createRoutesFromElements(
  <Route path='/' element={<Home />} errorElement={<HomeError /> } />
);

const componentRoutes = createRoutesFromElements(
  <Route path='/' Component={Home} ErrorBoundary={HomeError} />
);

function Home() { ... }
function HomeError() { ... }

引入惰性路由模块

为了保持您的应用程序 bundle 小巧并支持路由的代码拆分,我们引入了一个新的 lazy() 路由属性。这是一个异步函数,它解析路由定义中非路由匹配的部分 (loaderactionelement/ComponenterrorElement/ErrorBoundaryshouldRevalidatehandle)。

惰性路由在初始加载以及导航或 fetcher 调用的 loadingsubmitting 阶段解析。您无法惰性地定义路由匹配属性 (pathindexchildren),因为我们仅在匹配已知路由后才执行您的惰性路由函数。

您的 lazy 函数通常会返回动态导入的结果。

// In this example, we assume most folks land on the homepage so we include that
// in our critical-path bundle, but then we lazily load modules for /a and /b so
// they don't load until the user navigates to those routes
let routes = createRoutesFromElements(
  <Route path="/" element={<Layout />}>
    <Route index element={<Home />} />
    <Route path="a" lazy={() => import("./a")} />
    <Route path="b" lazy={() => import("./b")} />
  </Route>
);

然后在您的惰性路由模块中,导出您想要为路由定义的属性

export async function loader({ request }) {
  let data = await fetchData(request);
  return json(data);
}

// Export a `Component` directly instead of needing to create a React Element from it
export function Component() {
  let data = useLoaderData();

  return (
    <>
      <h1>You made it!</h1>
      <p>{data}</p>
    </>
  );
}

// Export an `ErrorBoundary` directly instead of needing to create a React Element from it
export function ErrorBoundary() {
  let error = useRouteError();
  return isRouteErrorResponse(error) ? (
    <h1>
      {error.status} {error.statusText}
    </h1>
  ) : (
    <h1>{error.message || error}</h1>
  );
}

可以在仓库的 examples/lazy-loading-router-provider 目录中找到此操作的示例。有关更多信息,请查看 lazy 文档

🙌 非常感谢 @rossipedia 的 初始提案POC 实现

次要更改

  • 添加对 route.Component/route.ErrorBoundary 属性的支持 (<#10045>)
  • 添加对 route.lazy 的支持 (<#10045>)

补丁更新

  • 改进上下文提供程序的 memoization 以避免不必要的重新渲染 (#9983)
  • 修复 generatePath 在某些情况下错误应用参数的问题 (#10078)
  • [react-router-dom-v5-compat] 添加遗漏的数据路由器 API 重新导出 (#10171)

完整更新日志: v6.8.2...v6.9.0

v6.8.2

日期: 2023-02-27

补丁更新

  • <Link to> 中的同源绝对 URL 视为外部链接,如果它们在路由器 basename 之外 (#10135)
  • 正确地为路由器 basename 之外的同源绝对 URL 执行硬重定向 (#10076)
  • 修复绝对 <Link to> URL 的 SSR 问题 (#10112)
  • 正确转义 StaticRouterProvider 序列化 hydration 数据中的 HTML 字符 (#10068)
  • 修复 useBlocker 在 SSR 期间返回 IDLE_BLOCKER 的问题 (#10046)
  • 确保在 createStaticHandlerquery() 方法中为 defer loader 响应维护状态代码和标头 (#10077)
  • invariant 更改为 UNSAFE_invariant 导出,因为它仅供内部使用 (#10066)

完整更新日志: v6.8.1...v6.8.2

v6.8.1

日期: 2023-02-06

补丁更新

  • 移除 POP 导航的不准确控制台警告,并更新活动 blocker 逻辑 (#10030)
  • 仅在绝对 URL 重定向上检查不同的来源 (#10033)
  • 改进了 Link 组件中的绝对 URL 检测(现在也支持 mailto: URL) (#9994)
  • 修复部分对象(仅搜索或哈希)路径名丢失当前路径值的问题 (#10029)

完整更新日志: v6.8.0...v6.8.1

v6.8.0

日期: 2023-01-26

小版本更新

支持 <Link to> 中的绝对 URL。如果 URL 指向当前来源,它仍将执行客户端导航。如果 URL 指向不同的来源,则它将为新来源执行全新的文档请求。 (#9900)

<Link to="https://neworigin.com/some/path">    {/* Document request */}
<Link to="//neworigin.com/some/path">          {/* Document request */}
<Link to="https://www.currentorigin.com/path"> {/* Client-side navigation */}

补丁更新

  • 修复了重新验证 fetcher shouldRevalidate 调用的 2 个独立问题 (#9948)
    • shouldRevalidate 函数仅在显式重新验证场景(在 mutation 之后、手动 useRevalidator 调用或用于 Remix 中 cookie 设置的 X-Remix-Revalidate 标头)中被调用。它没有在隐式重新验证场景中被正确调用,这些场景也适用于导航 loader 重新验证,例如搜索参数的更改或单击我们已在的页面的链接。现在在这些额外的场景中已正确调用。
    • 传递的参数不正确且彼此不一致,因为 current*/next* 参数反映了静态 fetcher.load URL(因此是相同的)。相反,它们应该反映触发重新验证的导航(如 form* 参数所做的那样)。这些参数现在正确地反映了触发导航。
  • 修复了通过 useSearchParams 删除搜索参数的错误 (#9969)
  • 尊重 <fetcher.Form> 上的 preventScrollReset 属性 (#9963)
  • 修复了手动 URL 更改时哈希路由器的导航问题 (#9980)
  • <ScrollRestoration> 使用 pagehide 而不是 beforeunload。这具有更好的跨浏览器支持,尤其是在移动 Safari 上。 (#9945)
  • 不要在仅哈希更改的 mutation 提交上短路 (#9944)
  • isRouteErrorResponse 中删除 instanceof 检查,以避免服务器上的捆绑问题 (#9930)
  • 检测 defer 调用何时仅包含关键数据并删除 AbortController (#9965)
  • 在 URL 编码 File FormData 条目时发送名称作为值 (#9867)
  • react-router-dom-v5-compat - 修复了使用 CompatRouter 时 SSR useLayoutEffect console.error 的问题 (#9820)

完整更新日志: v6.7.0...v6.8.0

v6.7.0

日期: 2023-01-18

小版本更新

  • 添加 unstable_useBlocker/unstable_usePrompt 钩子,用于阻止应用程序位置来源内的导航 (#9709, #9932)
  • <Form> 添加 preventScrollReset 属性 (#9886)

补丁更新

  • useBeforeUnload 添加了直通事件监听器选项参数 (#9709)
  • 修复了存在可选参数时 generatePath 的问题 (#9764)
  • 更新 <Await> 以接受 ReactNode 作为子函数返回结果 (#9896)
  • 改进了 actions/loaders 中的绝对重定向 URL 检测 (#9829)
  • 修复了内存历史记录的 URL 创建问题 (#9814)
  • 修复了提交重定向时的滚动重置问题 (#9886)
  • 修复了同源绝对重定向的 404 错误 (#9913)
  • 简化了测试中 jsdom 错误解决方法 (#9824)

完整更新日志: v6.6.2...v6.7.0

v6.6.2

日期: 2023-01-09

补丁更新

  • 确保 SSR 期间 useId 的一致性 (#9805)

完整更新日志: v6.6.1...v6.6.2

v6.6.1

日期: 2022-12-23

补丁更新

  • 在操作重定向的 shouldRevalidate 中包含提交信息 (#9777, #9782)
  • 在操作重定向到当前位置时重置 actionData (#9772)

完整更新日志: v6.6.0...v6.6.1

v6.6.0

日期: 2022-12-21

更新内容

此小版本发布主要是为了稳定数据路由器的 SSR API,因为我们已在 Remix 中连接了新的 RouterProvider,作为 React Router-ing Remix 工作的一部分。

小版本更新

  • createStaticHandler/createStaticRouter/StaticRouterProvider 中删除 unstable_ 前缀 (#9738)
  • 添加 useBeforeUnload() 钩子 (#9664)

补丁更新

  • 支持大写 <Form method>useSubmit 方法值 (#9664)
  • 修复 <button formmethod> 表单提交覆盖问题 (#9664)
  • 修复了提交时的显式 replace 和提交到新路径时的 PUSH 问题 (#9734)
  • 阻止在 errorElement 中使用 useLoaderData (#9735)
  • 正确 hydration 来自 StaticRouterProviderError 对象 (#9664)
  • 跳过带有 hydrationData 的 SSR 应用程序的初始滚动恢复 (#9664)
  • 修复了一些错误,这些错误导致 loader/action 数据在错误时未被正确清除 (#9735)

完整更新日志: v6.5.0...v6.6.0

v6.5.0

日期: 2022-12-16

更新内容

此版本引入了对 可选路由段 的支持。现在,在任何路径段的末尾添加 ? 将使整个段变为可选。这适用于静态段和动态参数。

可选参数示例

  • <Route path=":lang?/about> 将匹配
    • /:lang/about
    • /about
  • <Route path="/multistep/:widget1?/widget2?/widget3?"> 将匹配
    • /multistep
    • /multistep/:widget1
    • /multistep/:widget1/:widget2
    • /multistep/:widget1/:widget2/:widget3

可选静态段示例

  • <Route path="/home?"> 将匹配
    • /
    • /home
  • <Route path="/fr?/about"> 将匹配
    • /about
    • /fr/about

小版本更新

  • 允许可选路由和可选静态段 (#9650)

补丁更新

  • 停止错误地匹配部分命名参数,即 <Route path="prefix-:param">,以与 splat 参数的工作方式保持一致。如果您之前依赖此行为,则建议在 useParams 调用站点提取路径的静态部分: (#9506)
// Old behavior at URL /prefix-123
<Route path="prefix-:id" element={<Comp /> }>

function Comp() {
  let params = useParams(); // { id: '123' }
  let id = params.id; // "123"
  ...
}

// New behavior at URL /prefix-123
<Route path=":id" element={<Comp /> }>

function Comp() {
  let params = useParams(); // { id: 'prefix-123' }
  let id = params.id.replace(/^prefix-/, ''); // "123"
  ...
}
  • 在 SSR 文档 action 请求后,持久化 loader requestheaders (#9721)
  • 修复发送到重新验证 loaders 的请求,使其反映 GET 请求 (#9660)
  • 修复了深度嵌套的可选段的问题 (#9727)
  • GET 表单现在在加载导航上公开提交 (#9695)
  • 修复了多个错误冒泡到同一边界的错误边界跟踪问题 (#9702)

完整更新日志: v6.4.5...v6.5.0

v6.4.5

日期: 2022-12-07

补丁更新

  • 修复发送到重新验证 loaders 的请求,使其反映 GET 请求 (#9680)
  • 移除 instanceof Response 检查,而使用 isResponse (#9690)
  • 修复 Cloudflare Pages 或其他非浏览器环境中 URL 创建的问题 (#9682, #9689)
  • 向静态处理程序 query/queryRoute 添加 requestContext 支持 (#9696)
    • 请注意,queryRoute(path, routeId) 的不稳定 API 已更改为 queryRoute(path, { routeId, requestContext })

完整更新日志: v6.4.4...v6.4.5

v6.4.4

日期: 2022-11-30

补丁更新

  • 如果 action/loader 函数返回 undefined,则会抛出错误,因为重新验证需要知道 loader 之前是否已执行。undefined 还会导致 SSR 字符串化以进行 hydration 时出现问题。您应始终确保您的 loader/action 返回一个值,如果您不希望返回任何内容,则可以返回 null。 (#9511)
  • 正确处理重定向到外部域的问题 (#9590, #9654)
  • 在 307/308 重定向中保留 HTTP 方法 (#9597)
  • 支持静态数据路由器中的 basename (#9591)
  • 增强了 ErrorResponse body,以便在内部 403/404/405 场景中包含更具描述性的文本
  • 修复了 NavLink 和后代 <Routes> 中编码字符的问题 (#9589, #9647)
  • 在使用内置 hydration 时正确序列化/反序列化 ErrorResponse 实例 (#9593)
  • 支持静态数据路由器中的 basename (#9591)
  • 更新的依赖项
    • @remix-run/router@1.0.4
    • react-router@6.4.4

完整更新日志: v6.4.3...v6.4.4

v6.4.3

日期: 2022-11-01

补丁更新

  • 在使用 createHashRouter 时生成正确的 <a href> 值 (#9409)
  • 更好地处理 URL 和路由路径中特殊字符的编码/匹配问题 (#9477, #9496)
  • index 路由也具有 path 时,生成正确的 formAction 路径名 (#9486)
  • 尊重 NavLink 上的 relative=path 属性 (#9453)
  • 修复根 URL 的 NavLink 行为 (#9497)
  • 当传递 locationArg 时,useRoutes 应该能够返回 null (#9485)
  • 修复 createMemoryRouter 中的 initialEntries 类型 (#9498)
  • 支持 loader/action 重定向中的 basename 和相对路由 (#9447)
  • 在查找正确的提交 action 函数时,忽略无路径布局路由 (#9455)
  • @remix-run/router 添加 UMD 构建 (#9446)
  • 修复 Firefox 中本地文件执行中的 createURL 问题 (#9464)

完整更新日志: v6.4.2...v6.4.3

v6.4.2

日期: 2022-10-06

补丁更新

  • 尊重 useFormAction 中的 basename (#9352)
  • 修复 IndexRouteObjectNonIndexRouteObject 类型,使 hasErrorElement 成为可选 (#9394)
  • 增强了数据路由器钩子的无效用法的控制台错误消息 (#9311)
  • 如果索引路由有子路由,则会导致运行时错误。我们加强了 RouteObject/RouteProps 类型,以便在 TypeScript 中显示错误。 (#9366)

完整更新日志: v6.4.1...v6.4.2

v6.4.1

日期: 2022-09-22

补丁更新

  • 保留来自 initialEntries 的状态 (#9288)
  • 为 fetcher get 提交到索引路由保留 ?index (#9312)

完整更新日志: v6.4.0...v6.4.1

v6.4.0

日期: 2022-09-13

更新内容

Remix 数据 API

哇,这是一个重要的版本!6.4.0 带来了来自 Remix 的所有数据加载和 mutation API。这是一个快速的高级概述,但建议您查看 文档,特别是 功能概述教程

新的 react-router API

  • 使用 createMemoryRouter 创建您的路由器
  • 使用 <RouterProvider> 渲染您的路由器
  • 使用路由 loader 加载数据,并使用路由 action 进行 mutation
  • 使用路由 errorElement 处理错误
  • 使用 deferAwait 延迟非关键数据

新的 react-router-dom API

  • 使用 createBrowserRouter/createHashRouter 创建您的路由器
  • 使用新的 <Form> 组件提交数据
  • 使用 useFetcher() 执行页面内数据加载和 mutation
  • 使用 deferAwait 延迟非关键数据
  • 使用 <ScrollRestoration> 管理滚动位置
  • 使用 <Link relative="path"> 执行路径相对导航 (#9160)

补丁更新

  • 路径解析现在与尾部斜杠无关 (#8861)
  • useLocation 返回 <Routes location> 组件内的作用域位置 (#9094)
  • 如果定义了 <Link replace> 属性,则尊重该属性 (#8779)

完整更新日志: v6.3.0...v6.4.0

v6.3.0

日期: 2022-03-31

小版本更新

  • 添加了 v5 到 v6 的向后兼容性包 💜 (#8752)。官方指南可以在 此讨论 中找到

完整更新日志: v6.2.2...v6.3.0

v6.2.2

日期: 2022-02-28

补丁更新

  • 修复了以特殊 URL 安全字符开头的嵌套 splat 路由问题 (#8563)
  • 修复了在某些情况下索引路由缺少路由上下文的错误 (#8497)

完整更新日志: v6.2.1...v6.2.2

v6.2.1

日期: 2021-12-17

补丁更新

  • 此版本将内部 history 依赖项更新为 5.2.0

完整更新日志: v6.2.0...v6.2.1

v6.2.0

日期: 2021-12-17

小版本更新

  • 我们现在使用静态可分析的 CJS 导出。这使得 Node ESM 脚本中的命名导入成为可能 (查看提交)。

补丁更新

  • 修复了 RouteProps element 类型,它应该是 ReactNode (#8473)
  • 修复了顶级路由的 useOutlet 错误 (#8483)

完整更新日志: v6.1.1...v6.2.0

v6.1.1

日期: 2021-12-11

补丁更新

  • 在 v6.1.0 中,我们无意中发布了一个新的、未记录的 API,这可能会引入错误 (#7586)。我们将 HistoryRouter 标记为 unstable_HistoryRouter,因为此 API 在新的主要版本发布之前可能需要更改。

完整更新日志: v6.1.0...v6.1.1

v6.1.0

日期: 2021-12-10

小版本更新

  • <Outlet> 现在可以接收 context 属性。此值将传递给子路由,并且可以通过新的 useOutletContext 钩子访问。有关详细信息,请参阅 API 文档。 (#8461)
  • <NavLink> 现在可以接收子函数以访问其属性。 (#8164)
  • 改进了 useMatchmatchPath 的 TypeScript 签名。例如,当您调用 useMatch("foo/:bar/:baz") 时,路径将被解析,并且返回类型将为 PathMatch<"bar" | "baz">。 (#8030)

补丁更新

  • 修复了破坏嵌套路由上 base64 编码 ID 支持的错误 (#8291)
  • 一些错误消息改进 (#8202)

完整更新日志: v6.0.2...v6.1.0

v6.0.2

日期: 2021-11-09

补丁更新

  • <Link> 添加了 reloadDocument 属性。这允许 <Link> 像正常的锚标记一样工作,方法是在导航后重新加载文档,同时保持相对 to 解析 (#8283)

完整更新日志: v6.0.1...v6.0.2

v6.0.1

日期: 2021-11-05

补丁更新

  • 添加默认的 <StaticRouter location> 值 (#8243)
  • 添加了在 <Routes> 内部使用 <Route> 的 invariant,以帮助人们进行更改 (#8238)

完整更新日志: v6.0.0...v6.0.1

v6.0.0

日期: 2021-11-03

React Router v6 发布啦!

请阅读 我们的博客文章,了解 v6 中所有精彩内容的更多信息,包括 关于如何从 React Router v5 和 Reach Router 升级的说明

文档和示例 CC 4.0