Skip to content

Releases: remix-run/react-router

v6.15.0

10 Aug 14:57
e79cb77
Compare
Choose a tag to compare

Minor Changes

  • Add's a new redirectDocument() function which allows users to specify that a redirect from a loader/action should trigger a document reload (via window.location) instead of attempting to navigate to the redirected location via React Router (#10705)

Patch Changes

  • Ensure useRevalidator is referentially stable across re-renders if revalidations are not actively occurring (#10707)
  • Ensure hash history always includes a leading slash on hash pathnames (#10753)
  • Fixes an edge-case affecting web extensions in Firefox that use URLSearchParams and the useSearchParams hook (#10620)
  • Reorder effects in unstable_usePrompt to avoid throwing an exception if the prompt is unblocked and a navigation is performed synchronously (#10687, #10718)
  • SSR: Do not include hash in useFormAction() for unspecified actions since it cannot be determined on the server and causes hydration issues (#10758)
  • SSR: Fix an issue in queryRoute that was not always identifying thrown Response instances (#10717)
  • react-router-native: Update @ungap/url-search-params dependency from ^0.1.4 to ^0.2.2 (#10590)

Full Changelog: https://github.com/remix-run/react-router/compare/[email protected]@6.15.0

v6.14.2

17 Jul 20:55
1acea8b
Compare
Choose a tag to compare

Patch Changes

  • Add missing <Form state> prop to populate history.state on submission navigations (#10630)
  • Trigger an error if a defer promise resolves/rejects with undefined in order to match the behavior of loaders and actions which must return a value or null (#10690)
  • Properly handle fetcher redirects interrupted by normal navigations (#10674)
  • Initial-load fetchers should not automatically revalidate on GET navigations (#10688)
  • Properly decode element id when emulating hash scrolling via <ScrollRestoration> (#10682)
  • Typescript: Enhance the return type of Route.lazy to prohibit returning an empty object (#10634)
  • SSR: Support proper hydration of Error subclasses such as ReferenceError/TypeError (#10633)

Full Changelog: https://github.com/remix-run/react-router/compare/[email protected]@6.14.2

v6.14.1

30 Jun 19:16
8be5e51
Compare
Choose a tag to compare

Patch Changes

  • Fix loop in unstable_useBlocker when used with an unstable blocker function (#10652)
  • Fix issues with reused blockers on subsequent navigations (#10656)
  • Updated dependencies:

Full Changelog: https://github.com/remix-run/react-router/compare/[email protected]@6.14.1

v6.14.0

23 Jun 20:00
09b6cbe
Compare
Choose a tag to compare

What's Changed

JSON/Text Submissions

6.14.0 adds support for JSON and Text submissions via useSubmit/fetcher.submit since it's not always convenient to have to serialize into FormData if you're working in a client-side SPA. To opt-into these encodings you just need to specify the proper formEncType:

Opt-into application/json encoding:

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" }
}

Opt-into text/plain encoding:

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"
}

⚠️ Default Behavior Will Change in v7

Please note that to avoid a breaking change, the default behavior will still encode a simple key/value JSON object into a FormData instance:

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
}

This behavior will likely change in v7 so it's best to make any JSON object submissions explicit with formEncType: "application/x-www-form-urlencoded" or formEncType: "application/json" to ease your eventual v7 migration path.

Minor Changes

  • Add support for application/json and text/plain encodings for useSubmit/fetcher.submit. To reflect these additional types, useNavigation/useFetcher now also contain navigation.json/navigation.text and fetcher.json/fetcher.text which include the json/text submission if applicable. (#10413)

Patch Changes

  • When submitting a form from a submitter element, prefer the built-in new FormData(form, submitter) instead of the previous manual approach in modern browsers (those that support the new submitter parameter) (#9865)
    • For browsers that don't support it, we continue to just append the submit button's entry to the end, and we also add rudimentary support for type="image" buttons
    • If developers want full spec-compliant support for legacy browsers, they can use the formdata-submitter-polyfill
  • Call window.history.pushState/replaceState before updating React Router state (instead of after) so that window.location matches useLocation during synchronous React 17 rendering (#10448)
    • ⚠️ Note: generally apps should not be relying on window.location and should always reference useLocation when possible, as window.location will not be in sync 100% of the time (due to popstate events, concurrent mode, etc.)
  • Avoid calling shouldRevalidate for fetchers that have not yet completed a data load (#10623)
  • Strip basename from the location provided to <ScrollRestoration getKey> to match the useLocation behavior (#10550)
  • Strip basename from locations provided to unstable_useBlocker functions to match the useLocation behavior (#10573)
  • Fix unstable_useBlocker key issues in StrictMode (#10573)
  • Fix generatePath when passed a numeric 0 value parameter (#10612)
  • Fix tsc --skipLibCheck:false issues on React 17 (#10622)
  • Upgrade typescript to 5.1 (#10581)

Full Changelog: https://github.com/remix-run/react-router/compare/[email protected]@6.14.0

v6.13.0

14 Jun 16:01
ed17fcd
Compare
Choose a tag to compare

What's Changed

6.13.0 is really a patch release in spirit but comes with a SemVer minor bump since we added a new future flag.

The tl;dr; is that 6.13.0 is the same as 6.12.0 bue we've moved the usage of React.startTransition behind an opt-in future.v7_startTransition future flag because we found that there are applications in the wild that are currently using Suspense in ways that are incompatible with React.startTransition.

Therefore, in 6.13.0 the default behavior will no longer leverage React.startTransition:

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

<RouterProvider router={router} />

If you wish to enable React.startTransition, pass the future flag to your router component:

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

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

We recommend folks adopt this flag sooner rather than later to be better compatible with React concurrent mode, but if you run into issues you can continue without the use of React.startTransition until v7. Issues usually boil down to creating net-new promises during the render cycle, so if you run into issues when opting into React.startTransition, you should either lift your promise creation out of the render cycle or put it behind a useMemo.

Minor Changes

  • Move React.startTransition usage behinds a future flag (#10596)

Patch Changes

  • Work around webpack/terser React.startTransition minification bug in production mode (#10588)

Full Changelog: https://github.com/remix-run/react-router/compare/[email protected]@6.13.0

v6.12.1

08 Jun 16:49
77d7182
Compare
Choose a tag to compare

Warning
Please use version 6.13.0 or later instead of 6.12.0/6.12.1. These versions suffered from some Webpack build/minification issues resulting failed builds or invalid minified code in your production bundles. See #10569 and #10579 for more details.

Patch Changes

  • Adjust feature detection of React.startTransition to fix webpack + react 17 compilation error (#10569)

Full Changelog: https://github.com/remix-run/react-router/compare/[email protected]@6.12.1

v6.12.0

06 Jun 18:29
6c0bbb1
Compare
Choose a tag to compare

Warning
Please use version 6.13.0 or later instead of 6.12.0/6.12.1. These versions suffered from some Webpack build/minification issues resulting failed builds or invalid minified code in your production bundles. See #10569 and #10579 for more details.

What's Changed

With 6.12.0 we've added better support for suspending components by wrapping the internal router state updates in React.startTransition. This means that, for example, if one of your components in a destination route suspends and you have not provided a Suspense boundary to show a fallback, React will delay the rendering of the new UI and show the old UI until that asynchronous operation resolves. This could be useful for waiting for things such as waiting for images or CSS files to load (and technically, yes, you could use it for data loading but we'd still recommend using loaders for that 😀). For a quick overview of this usage, check out Ryan's demo on Twitter.

Minor Changes

  • Wrap internal router state updates with React.startTransition (#10438)

Patch Changes

  • Allow fetcher revalidations to complete if submitting fetcher is deleted (#10535)
  • Re-throw DOMException (DataCloneError) when attempting to perform a PUSH navigation with non-serializable state. (#10427)
  • Ensure revalidations happen when hash is present (#10516)
  • Upgrade jest and jsdom (#10453)
  • Updated dependencies:

Full Changelog: https://github.com/remix-run/react-router/compare/[email protected]@6.12.0

v6.11.2

17 May 15:34
0815c96
Compare
Choose a tag to compare

Patch Changes

  • Fix basename duplication in descendant <Routes> inside a <RouterProvider> (#10492)
  • Fix bug where initial data load would not kick off when hash is present (#10493)
  • Export SetURLSearchParams type (#10444)
  • Fix Remix HMR-driven error boundaries by properly reconstructing new routes and manifest in _internalSetRoutes (#10437)

Full Changelog: https://github.com/remix-run/react-router/compare/[email protected]@6.11.2

v6.11.1

03 May 20:36
db696c1
Compare
Choose a tag to compare

Patch Changes

  • Fix usage of Component API within descendant <Routes> (#10434)
  • Fix bug when calling useNavigate from <Routes> inside a <RouterProvider> (#10432)
  • Fix usage of <Navigate> in strict mode when using a data router (#10435)
  • Fix basename handling when navigating without a path (#10433)
  • "Same hash" navigations no longer re-run loaders to match browser behavior (i.e. /path#hash -> /path#hash) (#10408)

Full Changelog: https://github.com/remix-run/react-router/compare/[email protected]@6.11.1

v6.11.0

28 Apr 17:10
7ff51c0
Compare
Choose a tag to compare

What's Changed

Minor Changes

  • Enable basename support in useFetcher (#10336)
    • If you were previously working around this issue by manually prepending the basename then you will need to remove the manually prepended basename from your fetcher calls (fetcher.load('/basename/route') -> fetcher.load('/route'))
  • Updated dependencies:

Patch Changes

  • When using a RouterProvider, useNavigate/useSubmit/fetcher.submit are now stable across location changes, since we can handle relative routing via the @remix-run/router instance and get rid of our dependence on useLocation() (#10336)
    • When using BrowserRouter, these hooks remain unstable across location changes because they still rely on useLocation()
  • Fetchers should no longer revalidate on search params changes or routing to the same URL, and will only revalidate on action submissions or router.revalidate calls (#10344)
  • Fix inadvertent re-renders when using Component instead of element on a route definition (#10287)
  • Fail gracefully on <Link to="//"> and other invalid URL values (#10367)
  • Switched from useSyncExternalStore to useState for internal @remix-run/router router state syncing in <RouterProvider>. We found some subtle bugs where router state updates got propagated before other normal useState updates, which could lead to foot guns in useEffect calls. (#10377, #10409)
  • Log loader/action errors caught by the default error boundary to the console in dev for easier stack trace evaluation (#10286)
  • Fix bug preventing rendering of descendant <Routes> when RouterProvider errors existed (#10374)
  • Fix detection of useNavigate in the render cycle by setting the activeRef in a layout effect, allowing the navigate function to be passed to child components and called in a useEffect there (#10394)
  • Allow useRevalidator() to resolve a loader-driven error boundary scenario (#10369)
  • Enhance LoaderFunction/ActionFunction return type to prevent undefined from being a valid return value (#10267)
  • Ensure proper 404 error on fetcher.load call to a route without a loader (#10345)
  • Decouple AbortController usage between revalidating fetchers and the thing that triggered them such that the unmount/deletion of a revalidating fetcher doesn't impact the ongoing triggering navigation/revalidation (#10271)

Full Changelog: https://github.com/remix-run/react-router/compare/[email protected]@6.11.0