Skip to content

Commit f89b384

Browse files
committed
Stabilize unstable_dataStrategy
1 parent d573eff commit f89b384

File tree

11 files changed

+74
-67
lines changed

11 files changed

+74
-67
lines changed

.changeset/nasty-queens-leave.md

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
"react-router-dom": minor
3+
"react-router": minor
4+
"@remix-run/router": minor
5+
---
6+
7+
Stabilize `unstable_dataStrategy`

docs/routers/create-browser-router.md

+10-10
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ function createBrowserRouter(
5151
basename?: string;
5252
future?: FutureConfig;
5353
hydrationData?: HydrationState;
54-
unstable_dataStrategy?: unstable_DataStrategyFunction;
54+
dataStrategy?: DataStrategyFunction;
5555
unstable_patchRoutesOnNavigation?: unstable_PatchRoutesOnNavigationFunction;
5656
window?: Window;
5757
}
@@ -184,15 +184,15 @@ const router = createBrowserRouter(
184184
);
185185
```
186186

187-
## `opts.unstable_dataStrategy`
187+
## `opts.dataStrategy`
188188

189189
<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>
190190

191191
<docs-warning>This API is marked "unstable" so it is subject to breaking API changes in minor releases</docs-warning>
192192

193193
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.
194194

195-
The `unstable_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.
195+
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.
196196

197197
### Type Declaration
198198

@@ -232,7 +232,7 @@ interface DataStrategyResult {
232232

233233
### Overview
234234

235-
`unstable_dataStrategy` receives the same arguments as a `loader`/`action` (`request`, `params`) but it also receives 2 new parameters: `matches` and `fetcherKey`:
235+
`dataStrategy` receives the same arguments as a `loader`/`action` (`request`, `params`) but it also receives 2 new parameters: `matches` and `fetcherKey`:
236236

237237
- **`matches`** - An array of the matched routes where each match is extended with 2 new fields for use in the data strategy function:
238238
- **`match.shouldLoad`** - A boolean value indicating whether this route handler should be called in this pass
@@ -247,9 +247,9 @@ interface DataStrategyResult {
247247
- It is safe to call `match.resolve` for all matches, even if they have `shouldLoad=false`, and it will no-op if no loading is required
248248
- You should generally always call `match.resolve()` for `shouldLoad:true` routes to ensure that any `route.lazy` implementations are processed
249249
- See the examples below for how to implement custom handler execution via `match.resolve`
250-
- **`fetcherKey`** - The key of the fetcher we are calling `unstable_dataStrategy` for, otherwise `null` for navigational executions
250+
- **`fetcherKey`** - The key of the fetcher we are calling `dataStrategy` for, otherwise `null` for navigational executions
251251

252-
The `dataStrategy` function should return a key/value object of `routeId -> DataStrategyResult` and should include entries for any routes where a handler was executed. A `DataStrategyResult` indicates if the handler was successful or not based on the `DataStrategyResult["type"]` field. If the returned `DataStrategyResult["result"]` is a `Response`, React Router will unwrap it for you (via `res.json` or `res.text`). If you need to do custom decoding of a `Response` but want to preserve the status code, you can use the `unstable_data` utility to return your decoded data along with a `ResponseInit`.
252+
The `dataStrategy` function should return a key/value object of `routeId -> DataStrategyResult` and should include entries for any routes where a handler was executed. A `DataStrategyResult` indicates if the handler was successful or not based on the `DataStrategyResult["type"]` field. If the returned `DataStrategyResult["result"]` is a `Response`, React Router will unwrap it for you (via `res.json` or `res.text`). If you need to do custom decoding of a `Response` but want to preserve the status code, you can use the `data` utility to return your decoded data along with a `ResponseInit`.
253253

254254
### Example Use Cases
255255

@@ -259,7 +259,7 @@ In the simplest case, let's look at hooking into this API to add some logging fo
259259

260260
```ts
261261
let router = createBrowserRouter(routes, {
262-
async unstable_dataStrategy({ request, matches }) {
262+
async dataStrategy({ request, matches }) {
263263
// Grab only the matches we need to run handlers for
264264
const matchesToLoad = matches.filter(
265265
(m) => m.shouldLoad
@@ -290,7 +290,7 @@ If you want to avoid the `reduce`, you can manually build up the `results` objec
290290

291291
```ts
292292
let router = createBrowserRouter(routes, {
293-
async unstable_dataStrategy({ request, matches }) {
293+
async dataStrategy({ request, matches }) {
294294
const matchesToLoad = matches.filter(
295295
(m) => m.shouldLoad
296296
);
@@ -353,7 +353,7 @@ const routes = [
353353
];
354354

355355
let router = createBrowserRouter(routes, {
356-
async unstable_dataStrategy({
356+
async dataStrategy({
357357
request,
358358
params,
359359
matches,
@@ -426,7 +426,7 @@ const routes = [
426426
];
427427

428428
let router = createBrowserRouter(routes, {
429-
unstable_dataStrategy({ request, params, matches }) {
429+
dataStrategy({ request, params, matches }) {
430430
// Compose route fragments into a single GQL payload
431431
let gql = getFragmentsFromRouteHandles(matches);
432432
let data = await fetchGql(gql);

packages/react-router-dom-v5-compat/index.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,10 @@ export type {
5151
ActionFunctionArgs,
5252
AwaitProps,
5353
BrowserRouterProps,
54-
unstable_DataStrategyFunction,
55-
unstable_DataStrategyFunctionArgs,
56-
unstable_DataStrategyMatch,
57-
unstable_DataStrategyResult,
54+
DataStrategyFunction,
55+
DataStrategyFunctionArgs,
56+
DataStrategyMatch,
57+
DataStrategyResult,
5858
DataRouteMatch,
5959
DataRouteObject,
6060
ErrorResponse,

packages/react-router-dom/index.tsx

+8-8
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import type {
1616
RouterProps,
1717
RouterProviderProps,
1818
To,
19-
unstable_DataStrategyFunction,
19+
DataStrategyFunction,
2020
unstable_PatchRoutesOnNavigationFunction,
2121
} from "react-router";
2222
import {
@@ -106,10 +106,10 @@ export type {
106106
BlockerFunction,
107107
DataRouteMatch,
108108
DataRouteObject,
109-
unstable_DataStrategyFunction,
110-
unstable_DataStrategyFunctionArgs,
111-
unstable_DataStrategyMatch,
112-
unstable_DataStrategyResult,
109+
DataStrategyFunction,
110+
DataStrategyFunctionArgs,
111+
DataStrategyMatch,
112+
DataStrategyResult,
113113
ErrorResponse,
114114
Fetcher,
115115
FutureConfig,
@@ -258,7 +258,7 @@ interface DOMRouterOpts {
258258
basename?: string;
259259
future?: Partial<Omit<RouterFutureConfig, "v7_prependBasename">>;
260260
hydrationData?: HydrationState;
261-
unstable_dataStrategy?: unstable_DataStrategyFunction;
261+
dataStrategy?: DataStrategyFunction;
262262
unstable_patchRoutesOnNavigation?: unstable_PatchRoutesOnNavigationFunction;
263263
window?: Window;
264264
}
@@ -277,7 +277,7 @@ export function createBrowserRouter(
277277
hydrationData: opts?.hydrationData || parseHydrationData(),
278278
routes,
279279
mapRouteProperties,
280-
unstable_dataStrategy: opts?.unstable_dataStrategy,
280+
dataStrategy: opts?.dataStrategy,
281281
unstable_patchRoutesOnNavigation: opts?.unstable_patchRoutesOnNavigation,
282282
window: opts?.window,
283283
}).initialize();
@@ -297,7 +297,7 @@ export function createHashRouter(
297297
hydrationData: opts?.hydrationData || parseHydrationData(),
298298
routes,
299299
mapRouteProperties,
300-
unstable_dataStrategy: opts?.unstable_dataStrategy,
300+
dataStrategy: opts?.dataStrategy,
301301
unstable_patchRoutesOnNavigation: opts?.unstable_patchRoutesOnNavigation,
302302
window: opts?.window,
303303
}).initialize();

packages/react-router-native/index.tsx

+4-4
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,10 @@ export type {
2727
BlockerFunction,
2828
DataRouteMatch,
2929
DataRouteObject,
30-
unstable_DataStrategyFunction,
31-
unstable_DataStrategyFunctionArgs,
32-
unstable_DataStrategyMatch,
33-
unstable_DataStrategyResult,
30+
DataStrategyFunction,
31+
DataStrategyFunctionArgs,
32+
DataStrategyMatch,
33+
DataStrategyResult,
3434
ErrorResponse,
3535
Fetcher,
3636
FutureConfig,

packages/react-router/__tests__/data-memory-router-test.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -3210,7 +3210,7 @@ describe("createMemoryRouter", () => {
32103210
/>
32113211
</Route>
32123212
),
3213-
{ initialEntries: ["/foo"], unstable_dataStrategy: urlDataStrategy }
3213+
{ initialEntries: ["/foo"], dataStrategy: urlDataStrategy }
32143214
);
32153215
let { container } = render(<RouterProvider router={router} />);
32163216

packages/react-router/index.ts

+10-10
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ import type {
44
ActionFunctionArgs,
55
Blocker,
66
BlockerFunction,
7-
unstable_DataStrategyFunction,
8-
unstable_DataStrategyFunctionArgs,
9-
unstable_DataStrategyMatch,
10-
unstable_DataStrategyResult,
7+
DataStrategyFunction,
8+
DataStrategyFunctionArgs,
9+
DataStrategyMatch,
10+
DataStrategyResult,
1111
ErrorResponse,
1212
Fetcher,
1313
HydrationState,
@@ -136,10 +136,10 @@ export type {
136136
AwaitProps,
137137
DataRouteMatch,
138138
DataRouteObject,
139-
unstable_DataStrategyFunction,
140-
unstable_DataStrategyFunctionArgs,
141-
unstable_DataStrategyMatch,
142-
unstable_DataStrategyResult,
139+
DataStrategyFunction,
140+
DataStrategyFunctionArgs,
141+
DataStrategyMatch,
142+
DataStrategyResult,
143143
ErrorResponse,
144144
Fetcher,
145145
FutureConfig,
@@ -302,7 +302,7 @@ export function createMemoryRouter(
302302
hydrationData?: HydrationState;
303303
initialEntries?: InitialEntry[];
304304
initialIndex?: number;
305-
unstable_dataStrategy?: unstable_DataStrategyFunction;
305+
dataStrategy?: DataStrategyFunction;
306306
unstable_patchRoutesOnNavigation?: unstable_PatchRoutesOnNavigationFunction;
307307
}
308308
): RemixRouter {
@@ -319,7 +319,7 @@ export function createMemoryRouter(
319319
hydrationData: opts?.hydrationData,
320320
routes,
321321
mapRouteProperties,
322-
unstable_dataStrategy: opts?.unstable_dataStrategy,
322+
dataStrategy: opts?.dataStrategy,
323323
unstable_patchRoutesOnNavigation: opts?.unstable_patchRoutesOnNavigation,
324324
}).initialize();
325325
}

packages/router/__tests__/ssr-test.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1602,7 +1602,7 @@ describe("ssr", () => {
16021602
let { query } = createStaticHandler(SSR_ROUTES);
16031603

16041604
let context = await query(createRequest("/custom"), {
1605-
unstable_dataStrategy: urlDataStrategy,
1605+
dataStrategy: urlDataStrategy,
16061606
});
16071607
expect(context).toMatchObject({
16081608
actionData: null,
@@ -2635,7 +2635,7 @@ describe("ssr", () => {
26352635
let data;
26362636

26372637
data = await queryRoute(createRequest("/custom"), {
2638-
unstable_dataStrategy: urlDataStrategy,
2638+
dataStrategy: urlDataStrategy,
26392639
});
26402640
expect(data).toBeInstanceOf(URLSearchParams);
26412641
expect((data as URLSearchParams).get("foo")).toBe("bar");

packages/router/__tests__/utils/data-router-setup.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -322,7 +322,7 @@ export function setup({
322322
hydrationData,
323323
future,
324324
window: testWindow,
325-
unstable_dataStrategy: dataStrategy,
325+
dataStrategy: dataStrategy,
326326
}).initialize();
327327

328328
function getRouteHelpers(

packages/router/index.ts

+5-5
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@ export type {
99
AgnosticNonIndexRouteObject,
1010
AgnosticRouteMatch,
1111
AgnosticRouteObject,
12-
DataStrategyFunction as unstable_DataStrategyFunction,
13-
DataStrategyFunctionArgs as unstable_DataStrategyFunctionArgs,
14-
DataStrategyMatch as unstable_DataStrategyMatch,
15-
DataStrategyResult as unstable_DataStrategyResult,
12+
DataStrategyFunction as DataStrategyFunction,
13+
DataStrategyFunctionArgs as DataStrategyFunctionArgs,
14+
DataStrategyMatch as DataStrategyMatch,
15+
DataStrategyResult as DataStrategyResult,
1616
ErrorResponse,
1717
FormEncType,
1818
FormMethod,
@@ -38,7 +38,7 @@ export type {
3838

3939
export {
4040
AbortedDeferredError,
41-
data as unstable_data,
41+
data,
4242
defer,
4343
generatePath,
4444
getToPathname,

0 commit comments

Comments
 (0)