react-router
Advanced tools
Changelog
v7.0.1
Date: 2024-11-22
react-router
@react-router/architect
@react-router/cloudflare
@react-router/dev
@react-router/express
@react-router/fs-routes
@react-router/node
@react-router/remix-config-routes-adapter
@react-router/serve
Full Changelog: v7.0.0...v7.0.1
Changelog
v7.0.0
Date: 2024-11-21
react-router-dom
, @remix-run/react
, @remix-run/server-runtime
, and @remix-run/router
have been collapsed into the react-router
package
react-router-dom
is still published in v7 as a re-export of everything from react-router
@remix-run/cloudflare-pages
and @remix-run/cloudflare-workers
have been collapsed into @react-router/cloudflare
package`react-router-dom-v5-compat
and react-router-native
packages are removed starting with v7Remix v2 used to re-export all common @remix-run/server-runtime
APIs through the various runtime packages (node
, cloudflare
, deno
) so that you wouldn't need an additional @remix-run/server-runtime
dependency in your package.json
. With the collapsing of packages into react-router
, these common APIs are now no longer re-exported through the runtime adapters. You should import all common APIs from react-router
, and only import runtime-specific APIs from the runtime packages:
// Runtime-specific APIs
import { createFileSessionStorage } from "@react-router/node";
// Runtime-agnostic APIs
import { redirect, useLoaderData } from "react-router";
The following APIs have been removed in React Router v7:
json
defer
unstable_composeUploadHandlers
unstable_createMemoryUploadHandler
unstable_parseMultipartFormData
React Router v7 requires the following minimum versions:
node@20
installGlobals
method to polyfill the fetch
APIreact@18
, react-dom@18
Remix and React Router follow an API Development Strategy leveraging "Future Flags" to avoid introducing a slew of breaking changes in a major release. Instead, breaking changes are introduce din minor releases behind a flag, allowing users to opt-in at their convenience. In the next major release, all future flag behaviors become the default behavior.
The following previously flagged behaviors are now the default in React Router v7:
future.v7_relativeSplatPath
future.v7_startTransition
future.v7_fetcherPersist
future.v7_normalizeFormMethod
future.v7_partialHydration
future.v7_skipActionStatusRevalidation
future.v3_fetcherPersist
future.v3_relativeSplatPath
future.v3_throwAbortReason
future.v3_singleFetch
future.v3_lazyRouteDiscovery
future.v3_optimizeDeps
The Remix Vite plugin is the proper way to build full-stack SSR apps using React Router v7. The former esbuild
-based compiler is no longer available.
Renamed vitePlugin
and cloudflareDevProxyVitePlugin
For Remix consumers migrating to React Router, the vitePlugin
and cloudflareDevProxyVitePlugin
exports have been renamed and moved (#11904)
-import {
- vitePlugin as remix,
- cloudflareDevProxyVitePlugin,
-} from "@remix/dev";
+import { reactRouter } from "@react-router/dev/vite";
+import { cloudflareDevProxy } from "@react-router/dev/vite/cloudflare";
Removed manifest
option
For Remix consumers migrating to React Router, the Vite plugin's manifest
option has been removed. The manifest
option been superseded by the more powerful buildEnd
hook since it's passed the buildManifest
argument. You can still write the build manifest to disk if needed, but you'll most likely find it more convenient to write any logic depending on the build manifest within the buildEnd
hook itself. (#11573)
If you were using the manifest
option, you can replace it with a buildEnd
hook that writes the manifest to disk like this:
// 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;
Because React 19 will have first-class support for handling promises in the render pass (via React.use
and useAction
), we are now comfortable exposing the promises for the APIs that previously returned undefined
:
useNavigate()
useSubmit()
useFetcher().load
useFetcher().submit
useRevalidator().revalidate()