You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Remove internal cache to fix issues with interrupted `patchRoutesOnNavigation` calls
6
+
7
+
- We used to cache in-progress calls to `patchRoutesOnNavigation` internally so that multiple navigations with the same start/end would only execute the function once and use the same promise
8
+
- However, this approach was at odds with `patch` short circuiting if a navigation was interrupted (and the `request.signal` aborted) since the first invocation's `patch` would no-op
9
+
- This cache also made some assumptions as to what a valid cache key might be - and is oblivious to any other application-state changes that may have occurred
10
+
- So, the cache has been removed because in _most_ cases, repeated calls to something like `import()` for async routes will already be cached automatically - and if not it's easy enough for users to implement this cache in userland
Copy file name to clipboardExpand all lines: docs/components/form.md
-2Lines changed: 0 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -285,8 +285,6 @@ See also: [`<Link preventScrollReset>`][link-preventscrollreset]
285
285
286
286
The `viewTransition` prop enables a [View Transition][view-transitions] for this navigation by wrapping the final state update in `document.startViewTransition()`. If you need to apply specific styles for this view transition, you will also need to leverage the [`useViewTransitionState()`][use-view-transition-state].
287
287
288
-
<docs-warning>Please note that this API is marked unstable and may be subject to breaking changes without a major release</docs-warning>
Copy file name to clipboardExpand all lines: docs/hooks/use-fetcher.md
-2Lines changed: 0 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -137,8 +137,6 @@ If you find yourself calling this function inside of click handlers, you can pro
137
137
138
138
The `flushSync` option tells React Router DOM to wrap the initial state update for this `fetcher.load` in a [`ReactDOM.flushSync`][flush-sync] call instead of the default [`React.startTransition`][start-transition]. This allows you to perform synchronous DOM actions immediately after the update is flushed to the DOM.
139
139
140
-
<docs-warning>Please note that this API is marked unstable and may be subject to breaking changes without a major release</docs-warning>
141
-
142
140
### `fetcher.submit()`
143
141
144
142
The imperative version of `<fetcher.Form>`. If a user interaction should initiate the fetch, you should use `<fetcher.Form>`. But if you, the programmer are initiating the fetch (not in response to a user clicking a button, etc.), then use this function.
Copy file name to clipboardExpand all lines: docs/hooks/use-navigate.md
-4Lines changed: 0 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -120,16 +120,12 @@ The `flushSync` option tells React Router DOM to wrap the initial state update f
120
120
121
121
<docs-warning>`flushSync` only works when using a data router, see [Picking a Router][picking-a-router]</docs-warning>
122
122
123
-
<docs-warning>Please note that this API is marked unstable and may be subject to breaking changes without a major release</docs-warning>
124
-
125
123
## `options.viewTransition`
126
124
127
125
The `viewTransition` option enables a [View Transition][view-transitions] for this navigation by wrapping the final state update in `document.startViewTransition()`. If you need to apply specific styles for this view transition, you will also need to leverage the [`useViewTransitionState()`][use-view-transition-state].
128
126
129
127
<docs-warning>`viewTransition` only works when using a data router, see [Picking a Router][picking-a-router]</docs-warning>
130
128
131
-
<docs-warning>Please note that this API is marked unstable and may be subject to breaking changes without a major release</docs-warning>
Copy file name to clipboardExpand all lines: docs/hooks/use-submit.md
-2Lines changed: 0 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -166,8 +166,6 @@ Because submissions are navigations, the options may also contain the other navi
166
166
167
167
The `flushSync` option tells React Router DOM to wrap the initial state update for this submission in a [`ReactDOM.flushSync`][flush-sync] call instead of the default [`React.startTransition`][start-transition]. This allows you to perform synchronous DOM actions immediately after the update is flushed to the DOM.
168
168
169
-
<docs-warning>Please note that this API is marked unstable and may be subject to breaking changes without a major release</docs-warning>
<docs-warning>This is a low-level API intended for advanced use-cases. This overrides React Router's internal handling of `loader`/`action` execution, and if done incorrectly will break your app code. Please use with caution and perform the appropriate testing.</docs-warning>
190
190
191
-
<docs-warning>This API is marked "unstable" so it is subject to breaking API changes in minor releases</docs-warning>
192
-
193
191
By default, React Router is opinionated about how your data is loaded/submitted - and most notably, executes all of your loaders in parallel for optimal data fetching. While we think this is the right behavior for most use-cases, we realize that there is no "one size fits all" solution when it comes to data fetching for the wide landscape of application requirements.
194
192
195
193
The `dataStrategy` option gives you full control over how your loaders and actions are executed and lays the foundation to build in more advanced APIs such as middleware, context, and caching layers. Over time, we expect that we'll leverage this API internally to bring more first class APIs to React Router, but until then (and beyond), this is your way to add more advanced functionality for your applications data needs.
@@ -436,11 +434,9 @@ let router = createBrowserRouter(routes, {
436
434
437
435
## `opts.patchRoutesOnNavigation`
438
436
439
-
<docs-warning>This API is marked "unstable" so it is subject to breaking API changes in minor releases</docs-warning>
440
-
441
437
By default, React Router wants you to provide a full route tree up front via `createBrowserRouter(routes)`. This allows React Router to perform synchronous route matching, execute loaders, and then render route components in the most optimistic manner without introducing waterfalls. The tradeoff is that your initial JS bundle is larger by definition - which may slow down application start-up times as your application grows.
442
438
443
-
To combat this, we introduced [`route.lazy`][route-lazy] in [v6.9.0][6-9-0] which let's you lazily load the route _implementation_ (`loader`, `Component`, etc.) while still providing the route _definition_ aspects up front (`path`, `index`, etc.). This is a good middle ground because React Router still knows about your routes up front and can perform synchronous route matching, but then delay loading any of the route implementation aspects until the route is actually navigated to.
439
+
To combat this, we introduced [`route.lazy`][route-lazy] in [v6.9.0][6-9-0] which let's you lazily load the route _implementation_ (`loader`, `Component`, etc.) while still providing the route _definition_ aspects up front (`path`, `index`, etc.). This is a good middle ground because React Router still knows about your route definitions (the lightweight part) up front and can perform synchronous route matching, but then delay loading any of the route implementation aspects (the heavier part) until the route is actually navigated to.
444
440
445
441
In some cases, even this doesn't go far enough. For very large applications, providing all route definitions up front can be prohibitively expensive. Additionally, it might not even be possible to provide all route definitions up front in certain Micro-Frontend or Module-Federation architectures.
In the above example, if the user clicks a link to `/a`, React Router won't be able to match it initially and will call `patchRoutesOnNavigation` with `/a` and a `matches` array containing the root route match. By calling `patch`, the `a` route will be added to the route tree and React Router will perform matching again. This time it will successfully match the `/a` path and the navigation will complete successfully.
488
+
In the above example, if the user clicks a link to `/a`, React Router won't match any routes initially and will call `patchRoutesOnNavigation` with a `path = "/a"` and a `matches` array containing the root route match. By calling `patch('root', [route])`, the new route will be added to the route tree as a child of the `root` route and React Router will perform matching on the updated routes. This time it will successfully match the `/a` path and the navigation will complete successfully.
493
489
494
490
**Patching new root-level routes**
495
491
@@ -544,6 +540,8 @@ let router = createBrowserRouter(
544
540
);
545
541
```
546
542
543
+
<docs-info>If in-progress execution of `patchRoutesOnNavigation` is interrupted by a subsequent navigation, then any remaining `patch` calls in the interrupted execution will not update the route tree because the operation was cancelled.</docs-info>
544
+
547
545
**Co-locating route discovery with route definition**
548
546
549
547
If you don't wish to perform your own pseudo-matching, you can leverage the partial `matches` array and the `handle` field on a route to keep the children definitions co-located:
0 commit comments