CHANGELOG.md
此页面

React Router 版本发布

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

我们在本文件中管理版本说明,而不是使用 Github 版本发布页面的分页功能,原因有两个

  • Github UI 中的分页意味着您无法轻松地一次搜索跨越大量版本的版本说明
  • 分页的 Github 界面还会在列表视图中截断较长的版本说明,没有任何提示,您需要点击进入详细信息视图才能查看完整的版本说明
目录

v7.0.2

日期:2024-12-02

补丁变更

  • 临时只在导出映射中使用一个构建,以便包可以对 react router 具有对等依赖关系 (#12437)

  • 支持 moduleResolution Node16NodeNext (#12440)

  • 为子路由生成宽松的 matchesparams 类型 (#12397)

    在运行时,matches 包含子路由匹配,params 包含子路由路径参数。但之前,我们只为父路由和 matchesparams 中的当前路由生成了类型。为了使我们生成的类型更接近运行时行为,我们现在在访问子路由信息时生成更宽松、更广泛的类型。

按包分类的变更

完整变更日志v7.0.1...v7.0.2

v7.0.1

日期:2024-11-22

补丁变更

  • 确保在 Vite 开发服务器重新启动时清理 typegen 文件观察器 (#12331)
  • 将路由错误作为 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 包中
  • 从 v7 开始,react-router-dom-v5-compatreact-router-native 包被移除

移除适配器重新导出

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

以下 API 已在 React Router v7 中移除

  • json
  • defer
  • unstable_composeUploadHandlers
  • unstable_createMemoryUploadHandler
  • unstable_parseMultipartFormData

最低版本

React Router v7 需要以下最低版本

  • node@20
    • React Router 不再提供 installGlobals 方法来 polyfill fetch API
  • react@18react-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;

暴露路由 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实现,转而使用通过单个fetch和turbo-stream的原生Promise(#11744
    • 这将从React Router中移除以下导出
      • defer
      • AbortedDeferredError
      • 类型 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
  • 为了在React 19 API中进行组合,从以下API公开底层的路由Promise:(#11521
  • 移除future.v7_normalizeFormMethod未来标志(#11697
  • 导入/导出清理(#11840
    • 移除以下导出,这些导出之前是@remix-run/router的公共API
      • 类型
        • 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
  • PrefetchPageDescriptorPageLinkDescriptor替换(#11960
  • 移除future.v7_partialHydration标志(#11725
    • 这也移除了<RouterProvider fallbackElement>属性
      • 要迁移,请将fallbackElement移动到根路由上的hydrateFallbackElement/HydrateFallback
    • 还值得注意的是,此未来标志存在相关的重大更改
      • 在没有future.v7_partialHydration的情况下(使用fallbackElement时),state.navigation在初始加载期间被填充
      • 使用future.v7_partialHydration时,state.navigation在初始加载期间保持"idle"状态
  • 移除future.v7_relativeSplatPath未来标志(#11695
  • 移除剩余的未来标志(#11820
    • React Router v7_skipActionErrorRevalidation
    • Remix v3_fetcherPersistv3_relativeSplatPathv3_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
  • 允许从加载程序和操作中返回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和会话API时,现在需要来自Web Crypto APIcrypto全局对象
    • 这意味着以下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 - 对于使用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,并且你的仓库中存在自定义的 entry.server.tsx 文件
      • 你无需进行任何更改
      • 你可以独立于 React Router v7 升级到 isbot@5
    • 如果你的 package.json 中包含 isbot@3,并且你的仓库中不存在自定义的 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 传递 (#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 - 删除内部 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() 从加载器/操作返回的重定向 (#12021)
  • @react-router/dev - 为资源路由启用预渲染 (#12200)
  • @react-router/dev - 将配置目录解析为相对于扁平输出文件结构的路径 (#12187)

按包分类的更改

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

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 (useSubmitfetcher.loadfetcher.submit) (文档)
  • unstable_viewTransitionviewTransition (<Link><Form>useNavigateuseSubmit) (文档)

次要更改

  • 稳定导航和获取器使用的 unstable_flushSync 选项 (#11989)
  • 稳定导航使用的 unstable_viewTransition 选项以及相应的 unstable_useViewTransitionState 钩子 (#11989)
  • 稳定 unstable_dataStrategy (#11974)
  • 稳定 unstable_patchRoutesOnNavigation (#11973)
    • 为方便起见,添加新的 PatchRoutesOnNavigationFunctionArgs 类型 (#11967)

补丁更改

  • 修复在先前提交中已存在 ?index 参数时,提交到当前上下文路由(具有索引子路由的父路由)时的错误 (#12003)
  • 修复 useFormAction 错误 - 删除 ?index 参数时,它不会保留其他非 Remix 的 index 参数 (#12003)
  • 修复获取器在并发获取期间通过重定向保留 preventScrollReset 的错误 (#11999)
  • 避免由于连续重新验证调用导致获取器中止时出现不必要的 console.error (#12050)
  • 修复在使用错误进行水合时出现的部分水合错误 (#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 参数,以允许区分导航和获取器调用
  • 通过重定向保留已选择加入的视图转换 (#11925)
  • 通过路由重新验证调用保留挂起的视图转换 (#11917)
  • 修复当 blocker.proceed 被快速/同步调用时的阻塞器使用问题 (#11930)

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

v6.26.1

日期: 2024-08-15

补丁更改

  • unstable_patchRoutesOnMiss 重命名为 unstable_patchRoutesOnNavigation 以匹配新的行为 (#11888)
  • 更新 unstable_patchRoutesOnNavigation 逻辑,以便在匹配具有动态参数或通配符段的路由时调用该方法,以防存在我们尚未发现的得分更高的静态路由 (#11883)
    • 我们现在还利用了一个内部的 FIFO 队列,其中存储了我们之前已经调用过 unstable_patchRoutesOnNavigation 的路径,这样我们就可以避免在随后导航到相同路径时重复调用

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

v6.26.0

日期: 2024-08-01

次要更改

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

补丁更改

  • 修复中断的获取器的内部清理,以避免在导航时发生无效的重新验证 (#11839)
  • 修复在使用 future.v7_partialHydration 以及 unstable_patchRoutesOnMiss 时初始水合的行为 (#11838)
    • 在初始水合期间,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 的操作默认情况下不会触发重新验证
  • 这也将 shouldRevalidateunstable_actionStatus 参数稳定化为 actionStatus

次要更改

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

补丁更改

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

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

v6.24.1

日期: 2024-07-03

补丁更改

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

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

v6.24.0

日期: 2024-06-24

更新内容

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

我们非常高兴在 v6.24.0 中发布我们新的“延迟路由发现”API!有关一些背景信息,请查看原始的 RFC简而言之,自从我们在 v6.4 中通过 <RouterProvider> 引入数据 API 以来,我们一直有点沮丧,因为其中一个权衡是缺少一个类似于我们在 <BrowserRouter>/<Routes> 应用程序中拥有的引人注目的代码拆分故事。我们在 v6.9.0 中通过 route.lazy 迈出了改进该故事的一小步,但在 v6.24.0 中,我们已经完成了剩下的工作。

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

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

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)
  • 允许传递给 <StaticRouter>location.state 值为假值 (#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 函数的数据策略的高级用例而设计。默认实现是今天的行为,并行获取所有加载器,但此选项允许用户实现更高级的数据流,包括 Remix "单次获取"、用户级中间件/上下文 API、自动加载器缓存等。请参阅 文档 以获取更多信息。

注意:这是一个专为高级用例设计的低级 API。这会覆盖 React Router 内部处理 loader/action 执行的方式,如果操作不当,将导致您的应用程序代码出错。请谨慎使用并进行适当的测试。

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

目前,所有活动的 loader 都会在任何 action 提交后重新验证,而不管 action 结果如何。但是,在大多数情况下,action 返回的 4xx/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 未来标志 (#11098)
  • @remix-run/router - SSR:在 staticHandler.query 方法中添加了一个新的 skipLoaderErrorBubbling 选项,以禁用静态处理程序的错误冒泡,用于 Remix 的单次获取实现 (#11098, (#11377))

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

v6.22.3

日期:2024-03-07

补丁更改

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

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

v6.22.2

日期:2024-02-28

补丁更改

  • 在部分 hydration 运行期间保留 hydration 错误 (#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

更新内容

核心 Web 指标技术报告标志

2021 年,HTTP Archive 推出了 核心 Web 指标技术报告仪表板

通过结合 Chrome UX Report 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 文件中的网站。这导致 大幅低估 Web 上 React Router 的使用情况。

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

次要更改

  • 包含 window.__reactRouterVersion 以进行 CWV 报告检测 (#11222)
  • createStaticHandler 添加 future.v7_throwAbortReason 标志,在请求被中止时抛出 request.signal.reason(默认为 DOMException),而不是像 new Error("query() call aborted: GET /path") 这样的 Error (#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

补丁更改

  • 修复了在指定 v7_partialHydration 时,route.lazy 在初始 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 路由路径解析错误,但后来确定大量应用程序依赖于有问题的行为,因此我们在 6.20.1 中撤回了修复程序(请参阅 #10983#11052#11078)。

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

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

部分 hydration

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

次要更改

  • 添加新的 future.v7_relativeSplatPath 标志,以实现对在 splat 路由内进行相对路由时的重大 bug 修复。(#11087)
  • 添加新的 future.v7_partialHydration 未来标志,用于在服务器端渲染时启用数据路由器的部分 hydration (#11033)

补丁更改

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

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

v6.20.1

日期:2023-12-01

补丁更改

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

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

v6.20.0

日期:2023-11-22

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

次要更改

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

补丁更改

  • 启用 v7_fetcherPersist 时,不要重新验证卸载的 fetcher (#11044)
  • 修复了 splat 路由中 resolveTo 路径解析的 bug (#11045)
    • 这是 #10983 的后续操作,用于处理使用 getPathContributingMatches 的其他几个代码路径

    • 此版本移除了 @remix-run/router 中的 UNSAFE_getPathContributingMatches 导出,因为我们在 react-router/react-router-dom 层中不再需要它。

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

v6.19.0

日期:2023-11-16

[!警告] 请使用 6.20.1 或更高版本,而不是 6.19.0。我们发现许多应用程序依赖于此版本中已修复的错误行为 (#10983)。我们在 6.20.1 中回滚了修复程序,并在后续版本中将其重新引入到一个未来的标志后面。有关更多详细信息,请参阅 #11052

变更内容

unstable_flushSync API

此版本为命令式 API(useSubmituseNavigatefetcher.submitfetcher.load)引入了新的 unstable_flushSync 选项,允许用户选择对挂起/乐观 UI 进行同步 DOM 更新。

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 钩子中删除 unstable_ 前缀,因为它已经使用了一段时间,我们对 API 充满信心 (#10991)
    • 我们不打算从 unstable_usePrompt 中删除前缀,因为浏览器处理 window.confirm 的方式存在差异,这阻止了 React Router 保证一致/正确的行为。

补丁变更

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

  • 修复 useResolvedPath 中的一个错误,该错误会导致在散列路由中 useResolvedPath(".") 丢失 URL 路径的散列部分。(#10983)

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

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

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

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

  • 修复 relative="path" 错误,其中相对路径计算从完整位置路径名开始,而不是从当前上下文路由路径名开始。(#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 实例,而无需进行 prop 传递。
  • Fetcher 密钥现在在从 useFetchers 返回的 Fetcher 上公开,以便可以通过 key 进行查找。
  • FormuseSubmit 现在支持可选的 navigate/fetcherKey 属性/参数,以允许在幕后启动 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.v7_fetcherPersist)

根据与上面相同的 RFC,我们引入了一个新的 future.v7_fetcherPersist 标志,允许您选择加入新的 Fetcher 持久性/清理行为。Fetcher 不会在卸载时立即清理,而是会一直持续到返回空闲状态。这使得在源 Fetcher 需要卸载的情况下,挂起/乐观 UI 变得非常容易。

  • 这有点像是一个长期存在的错误修复,因为 useFetchers() API 始终只反映挂起/乐观 UI 的进行中的 Fetcher 信息——它并非旨在反映 Fetcher 数据或在它们返回空闲状态后保留 Fetcher。
  • 选择加入此标志时,请注意以下具体行为更改,并检查您的应用程序的兼容性。
    • 在仍挂载状态下完成的 Fetcher 在完成之后将不再出现在 useFetchers() 中——因为您可以通过 useFetcher().data 访问数据,所以它们在那里没有任何用处。
    • 以前在进行中卸载的 Fetcher 不会立即中止,而是在返回空闲状态后进行清理。
      • 它们将在进行中通过 useFetchers 公开,因此您仍然可以在卸载后访问挂起/乐观数据。
      • 如果 Fetcher 在完成时不再挂载,则其结果将不会进行后处理——例如,不会遵循重定向,并且错误不会在 UI 中冒泡。
      • 但是,如果 Fetcher 在树中的其他地方使用相同的 key 重新挂载,则其结果将被处理,即使源 Fetcher 已卸载。

次要变更

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

补丁变更

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

完整变更日志6.17.0...6.18.0

v6.17.0

日期:2023-10-16

变更内容

视图过渡 🚀

我们很高兴在 React Router 中发布对 视图过渡 API 的实验性支持!您现在可以触发导航 DOM 更新以包装在 document.startViewTransition 中,以便在应用程序的 SPA 导航中启用 CSS 动画过渡。

在您的 React Router 应用程序中启用视图过渡的最简单方法是通过新的 <Link unstable_viewTransition> 属性。这将导致导航 DOM 更新包装在 document.startViewTransition 中,这将为 DOM 更新启用过渡。如果没有其他 CSS 样式,您将获得页面基本交叉淡入淡出动画。

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

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> 简写,它将为您管理钩子用法,并在过渡期间自动向 <a> 添加 transitioning 类。

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

有关视图过渡用法的示例,请查看我们对很棒的 Astro Records 演示的 fork

有关使用视图过渡 API 的更多信息,请参阅 Google Chrome 团队的 使用视图过渡 API 实现流畅简单的过渡 指南。

次要变更

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

补丁变更

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

完整变更日志6.16.0...6.17.0

v6.16.0

日期:2023-09-13

次要变更

  • 为了在未来转向更严格的 TypeScript 支持,我们的目标是将当前对 any 的用法替换为公开类型中用户提供数据的 unknown。为了在 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 向后兼容层且在 Remix v2 中不再需要的私有/内部 API(_isFetchActionRedirect_hasFetcherDoneAnything)(#10715

补丁更改

  • 在服务器渲染中正确编码渲染的 URI 以避免水合错误(#10769
  • 在中止的 query/queryRoute 调用中添加方法/URL 到错误消息(#10793
  • 修复 route.lazy 路由上加载器/操作抛出错误时的竞争条件(#10778
  • 修复传递给 shouldRevalidate 的参数对象上的 actionResult 类型(#10779

完整变更日志v6.15.0...v6.16.0

v6.15.0

日期:2023-08-10

次要更改

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

补丁更改

  • 如果重新验证没有积极发生,则确保 useRevalidator 在重新渲染时是引用稳定的(#10707
  • 确保哈希历史记录始终在哈希路径名上包含一个前导斜杠(#10753
  • 修复了影响 Firefox 中使用 URLSearchParamsuseSearchParams 钩子的 Web 扩展程序的边缘情况(#10620
  • 重新排序 unstable_usePrompt 中的 effect 以避免在提示解除阻止并同步执行导航时抛出异常(#10687#10718
  • SSR:对于未指定的 action,不要在 useFormAction() 中包含哈希,因为它无法在服务器上确定并会导致水合问题(#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> 属性以在提交导航时填充 history.state#10630
  • 如果 defer promise 使用 undefined 解析/拒绝,则触发错误,以匹配加载器和操作的行为,它们必须返回值或 null#10690
  • 正确处理被正常导航中断的 fetcher 重定向(#10674
  • 初始加载 fetcher 不应在 GET 导航上自动重新验证(#10688
  • 通过 <ScrollRestoration> 模拟哈希滚动时正确解码元素 ID(#10682
  • Typescript:增强 Route.lazy 的返回类型以禁止返回空对象(#10634
  • SSR:支持 Error 子类(如 ReferenceError/TypeError)的正确水合(#10633

完整变更日志v6.14.1...v6.14.2

v6.14.1

日期:2023-06-30

补丁更改

  • 修复与不稳定的 blocker 函数一起使用时 unstable_useBlocker 中的循环(#10652
  • 修复后续导航中重复使用的 blocker 的问题(#10656
  • 更新依赖项

完整变更日志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.submitapplication/jsontext/plain 编码的支持。为了反映这些附加类型,useNavigation/useFetcher 现在还包含 navigation.json/navigation.textfetcher.json/fetcher.text,如果适用,其中包含 json/文本提交。(#10413

补丁更改

  • submitter 元素提交表单时,优先使用内置的 new FormData(form, submitter) 而不是现代浏览器(支持新 submitter 参数的浏览器)中的先前手动方法(#9865
    • 对于不支持它的浏览器,我们继续将提交按钮的条目附加到末尾,并且我们还为 type="image" 按钮添加了基本支持
    • 如果开发人员希望获得对旧版浏览器的完全符合规范的支持,他们可以使用 formdata-submitter-polyfill
  • 在更新 React Router 状态之前调用 window.history.pushState/replaceState(而不是之后),以便在同步 React 17 渲染期间 window.locationuseLocation 匹配(#10448
    • ⚠️ 注意:通常应用程序不应该依赖 window.location,并且应该始终在可能的情况下引用 useLocation,因为 window.location 不会一直同步(由于 popstate 事件、并发模式等)。
  • 避免对尚未完成数据加载的 fetcher 调用 shouldRevalidate#10623
  • 从提供给 <ScrollRestoration getKey>location 中剥离 basename 以匹配 useLocation 行为(#10550
  • 从提供给 unstable_useBlocker 函数的 location 中剥离 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 实际上从精神上讲是一个补丁版本,但由于我们添加了一个新的未来标志,因此带有语义化版本次要更新。

future.v7_startTransition

简而言之6.13.06.12.0 相同,但我们将 React.startTransition 的使用移到了一个可选的 future.v7_startTransition 未来标志 后面,因为我们发现现实中存在一些应用程序以与 React.startTransition 不兼容的方式使用 Suspense

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

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

<RouterProvider router={router} />

如果您希望启用 React.startTransition,请将未来标志传递给您的路由器组件

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

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

我们建议大家尽早采用此标志以更好地与 React 并发模式兼容,但如果您遇到问题,您可以继续在没有 React.startTransition 的情况下使用,直到 v7 为止。问题通常归结为在渲染周期中创建新的 promise,因此如果您在选择加入 React.startTransition 时遇到问题,您应该将 promise 创建提升到渲染周期之外或将其放在 useMemo 后面。

次要更改

  • React.startTransition 的使用移到未来标志后面(#10596

补丁更改

  • 解决生产模式下 webpack/terser React.startTransition 缩小错误(#10588

完整变更日志v6.12.1...v6.13.0

v6.12.1

日期:2023-06-08

[!警告] 请使用 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

[!警告] 请使用 6.13.0 或更高版本,而不是 6.12.0/6.12.1。这些版本存在一些 Webpack 构建/压缩问题,导致构建失败或生产包中的代码压缩无效。更多详情请查看 #10569#10579

更新内容

React.startTransition 支持

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

次要更新

  • 使用 React.startTransition 包装内部路由状态更新 (#10438)

补丁更新

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

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

v6.11.2

日期: 2023-05-17

补丁更新

  • 修复 <RouterProvider> 内的子 <Routes> 中的 basename 重复问题 (#10492)
  • 修复存在哈希值时初始数据加载不会启动的错误 (#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 时出现的错误 (#10432)
  • 修复在使用数据路由时,严格模式下 <Navigate> 的用法 (#10435)
  • 修复导航没有路径时 basename 的处理 (#10433)
  • “相同哈希”导航不再重新运行加载器以匹配浏览器行为(例如 /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 时,这些钩子在位置更改中仍然不稳定,因为它们仍然依赖于 useLocation()
  • Fetchers 不应再在搜索参数更改或路由到相同 URL 时重新验证,并且仅在 action 提交或 router.revalidate 调用时重新验证 (#10344)
  • 修复在路由定义中使用 Component 而不是 element 时意外重新渲染的问题 (#10287)
  • <Link to="//"> 和其他无效 URL 值上优雅地失败 (#10367)
  • <RouterProvider> 中内部 @remix-run/router 路由器状态同步的 useSyncExternalStore 替换为 useState。我们发现了一些 细微的错误,其中路由器状态更新在其他正常的 useState 更新 *之前* 传播,这可能导致 useEffect 调用中的潜在问题。(#10377, #10409)
  • 在开发环境中将默认错误边界捕获的加载器/操作错误记录到控制台,以便更轻松地评估堆栈跟踪 (#10286)
  • 修复 RouterProvider 存在错误时阻止渲染子 <Routes> 的错误 (#10374)
  • 通过在布局效果中设置 activeRef 来修复渲染周期中 useNavigate 的检测,允许将 navigate 函数传递给子组件并在那里的 useEffect 中调用它 (#10394)
  • 允许 useRevalidator() 解决加载器驱动的错误边界场景 (#10369)
  • 增强 LoaderFunction/ActionFunction 返回类型,以防止 undefined 成为有效的返回值 (#10267)
  • 确保对没有 loader 的路由的 fetcher.load 调用返回正确的 404 错误 (#10345)
  • 将重新验证 fetchers 和触发它们的事件之间的 AbortController 使用解耦,以便重新验证 fetchers 的卸载/删除不会影响正在进行的触发导航/重新验证 (#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.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,除了 errorElement 之外,还要检查路由上的 ErrorBoundary (#10190)
  • 修复在 createRoutesFromElements 中使用片段时路由 ID 生成 (#10193)
  • 如果 fetcher 操作重定向,则将 fetcher 提交提供给 shouldRevalidate (#10208)
  • 正确处理路由器初始化期间的 lazy() 错误 (#10201)
  • 删除 DeferredDatainstanceof 检查,以增强在 SSR 捆绑场景中对 ESM/CJS 边界的弹性 (#10247)
  • 更新到最新的 @remix-run/[email protected] (#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() { ... }

引入延迟路由模块

为了使您的应用程序包保持较小规模并支持路由的代码拆分,我们引入了一个新的 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)

补丁更改

  • 改进上下文提供程序的记忆化,以避免不必要的重新渲染 (#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 之外,则将其视为外部 URL (#10135)
  • 对位于路由 basename 之外的同源绝对 URL 正确执行硬重定向 (#10076)
  • 修复绝对 <Link to> URL 的 SSR (#10112)
  • StaticRouterProvider 序列化水合数据中正确转义 HTML 字符 (#10068)
  • 修复 useBlocker 在 SSR 期间返回 IDLE_BLOCKER 的问题 (#10046)
  • 确保在 createStaticHandlerquery() 方法中维护 defer 加载程序响应的状态代码和标头 (#10077)
  • invariant 更改为 UNSAFE_invariant 导出,因为它仅用于内部使用 (#10066)

完整变更日志v6.8.1...v6.8.2

v6.8.1

日期:2023-02-06

补丁更改

  • 删除 POP 导航的不准确控制台警告并更新活动阻止程序逻辑 (#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 函数仅在显式重新验证场景(在变异、手动 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)
  • 不要在仅哈希更改的变异提交上短路 (#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)
  • 改进操作/加载程序中的绝对重定向 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,因为我们已将新的 RouterProvider 连接到 Remix 中,作为 React Router-ing Remix 工作的一部分。

次要更改

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

补丁更改

  • 支持大写 <Form method>useSubmit 方法值 (#9664)
  • 修复 <button formmethod> 表单提交覆盖问题 (#9664)
  • 修复提交上的显式 replace 和提交到新路径上的 PUSH (#9734)
  • 防止在 errorElement 中使用 useLoaderData (#9735)
  • 正确水合来自 StaticRouterProviderError 对象 (#9664)
  • 跳过具有 hydrationData 的 SSR 应用程序的初始滚动恢复 (#9664)
  • 修复一些在错误时加载程序/操作数据未正确清除的错误 (#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 request 上持久化 headers (#9721)
  • 修复发送到重新验证加载器的请求,使其反映 GET 请求 (#9660)
  • 修复深度嵌套可选段的问题 (#9727)
  • GET 表单现在在加载导航上公开提交 (#9695)
  • 修复多个错误冒泡到同一边界时的错误边界跟踪 (#9702)

完整更改日志v6.4.5...v6.5.0

v6.4.5

日期:2022-12-07

补丁更改

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

完整更改日志v6.4.4...v6.4.5

v6.4.4

日期:2022-11-30

补丁更改

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

完整更改日志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)
  • useRoutes 在传递 locationArg 时应该能够返回 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)
  • 保留 ?index 以便将 fetcher get 提交到索引路由 (#9312)

完整更改日志v6.4.0...v6.4.1

v6.4.0

日期:2022-09-13

更新内容

Remix 数据 API

哇,这是一个大版本!6.4.0 将所有数据加载和变异 API 从 Remix 中移植过来。这是一个快速的高级概述,但建议您查看 文档,特别是 功能概述教程

新的 react-router API

  • 使用 createMemoryRouter 创建路由器
  • 使用 <RouterProvider> 渲染路由器
  • 使用路由 loader 加载数据,并使用路由 action 变异数据
  • 使用路由 errorElement 处理错误
  • 使用 deferAwait 推迟非关键数据

新的 react-router-dom API

  • 使用 createBrowserRouter/createHashRouter 创建路由器
  • 使用新的 <Form> 组件提交数据
  • 使用 useFetcher() 执行页面内数据加载和变异
  • 使用 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> 添加不变量,以帮助用户进行更改 (#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