Skip to content

Commit f36a3b0

Browse files
committed
chore: generate markdown docs from jsdocs
1 parent aa95d1b commit f36a3b0

File tree

3 files changed

+59
-349
lines changed

3 files changed

+59
-349
lines changed

docs/api/data-routers/createBrowserRouter.md

Lines changed: 16 additions & 173 deletions
Original file line numberDiff line numberDiff line change
@@ -47,189 +47,32 @@ Basename path for the application.
4747

4848
### opts.dataStrategy
4949

50-
Override the default data strategy of running loaders in parallel.
51-
See [`DataStrategyFunction`](https://api.reactrouter.com/v7/interfaces/react_router.DataStrategyFunction.html).
52-
53-
<docs-warning>This is a low-level API intended for advanced use-cases. This
54-
overrides React Router's internal handling of
55-
[`action`](../../start/data/route-object#action)/[`loader`](../../start/data/route-object#loader)
56-
execution, and if done incorrectly will break your app code. Please use
57-
with caution and perform the appropriate testing.</docs-warning>
58-
59-
By default, React Router is opinionated about how your data is loaded/submitted -
60-
and most notably, executes all of your [`loader`](../../start/data/route-object#loader)s
61-
in parallel for optimal data fetching. While we think this is the right
62-
behavior for most use-cases, we realize that there is no "one size fits all"
63-
solution when it comes to data fetching for the wide landscape of
64-
application requirements.
65-
66-
The `dataStrategy` option gives you full control over how your [`action`](../../start/data/route-object#action)s
67-
and [`loader`](../../start/data/route-object#loader)s are executed and lays
68-
the foundation to build in more advanced APIs such as middleware, context,
69-
and caching layers. Over time, we expect that we'll leverage this API
70-
internally to bring more first class APIs to React Router, but until then
71-
(and beyond), this is your way to add more advanced functionality for your
72-
application's data needs.
73-
74-
The `dataStrategy` function should return a key/value-object of
75-
`routeId` -> [`DataStrategyResult`](https://api.reactrouter.com/v7/interfaces/react_router.DataStrategyResult.html) and should include entries for any
76-
routes where a handler was executed. A `DataStrategyResult` indicates if
77-
the handler was successful or not based on the `DataStrategyResult.type`
78-
field. If the returned `DataStrategyResult.result` is a [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response),
79-
React Router will unwrap it for you (via [`res.json`](https://developer.mozilla.org/en-US/docs/Web/API/Response/json)
80-
or [`res.text`](https://developer.mozilla.org/en-US/docs/Web/API/Response/text)).
81-
If you need to do custom decoding of a [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response)
82-
but want to preserve the status code, you can use the `data` utility to
83-
return your decoded data along with a `ResponseInit`.
84-
85-
<details>
86-
<summary><b>Example <code>dataStrategy</code> Use Cases</b></summary>
87-
88-
**Adding logging**
89-
90-
In the simplest case, let's look at hooking into this API to add some logging
91-
for when our route [`action`](../../start/data/route-object#action)s/[`loader`](../../start/data/route-object#loader)s
92-
execute:
50+
Override the default data strategy of running loaders in parallel -
51+
see the [docs](../../how-to/data-strategy) for more information.
9352

9453
```tsx
9554
let router = createBrowserRouter(routes, {
96-
async dataStrategy({ matches, request }) {
97-
const matchesToLoad = matches.filter((m) => m.shouldLoad);
98-
const results: Record<string, DataStrategyResult> = {};
99-
await Promise.all(
100-
matchesToLoad.map(async (match) => {
101-
console.log(`Processing ${match.route.id}`);
102-
results[match.route.id] = await match.resolve();;
103-
})
55+
async dataStrategy({
56+
matches,
57+
request,
58+
runClientMiddleware,
59+
}) {
60+
const matchesToLoad = matches.filter((m) =>
61+
m.shouldCallHandler(),
10462
);
105-
return results;
106-
},
107-
});
108-
```
109-
110-
**Middleware**
11163
112-
Let's define a middleware on each route via [`handle`](../../start/data/route-object#handle)
113-
and call middleware sequentially first, then call all
114-
[`loader`](../../start/data/route-object#loader)s in parallel - providing
115-
any data made available via the middleware:
116-
117-
```ts
118-
const routes = [
119-
{
120-
id: "parent",
121-
path: "/parent",
122-
loader({ request }, context) {
123-
// ...
124-
},
125-
handle: {
126-
async middleware({ request }, context) {
127-
context.parent = "PARENT MIDDLEWARE";
128-
},
129-
},
130-
children: [
131-
{
132-
id: "child",
133-
path: "child",
134-
loader({ request }, context) {
135-
// ...
136-
},
137-
handle: {
138-
async middleware({ request }, context) {
139-
context.child = "CHILD MIDDLEWARE";
140-
},
141-
},
142-
},
143-
],
144-
},
145-
];
146-
147-
let router = createBrowserRouter(routes, {
148-
async dataStrategy({ matches, params, request }) {
149-
// Run middleware sequentially and let them add data to `context`
150-
let context = {};
151-
for (const match of matches) {
152-
if (match.route.handle?.middleware) {
153-
await match.route.handle.middleware(
154-
{ request, params },
155-
context
156-
);
157-
}
158-
}
159-
160-
// Run loaders in parallel with the `context` value
161-
let matchesToLoad = matches.filter((m) => m.shouldLoad);
162-
let results = await Promise.all(
163-
matchesToLoad.map((match, i) =>
164-
match.resolve((handler) => {
165-
// Whatever you pass to `handler` will be passed as the 2nd parameter
166-
// to your loader/action
167-
return handler(context);
168-
})
169-
)
170-
);
171-
return results.reduce(
172-
(acc, result, i) =>
173-
Object.assign(acc, {
174-
[matchesToLoad[i].route.id]: result,
64+
const results: Record<string, DataStrategyResult> = {};
65+
await runClientMiddleware(() =>
66+
Promise.all(
67+
matchesToLoad.map(async (match) => {
68+
results[match.route.id] = await match.resolve();
17569
}),
176-
{}
70+
),
17771
);
178-
},
179-
});
180-
```
181-
182-
**Custom Handler**
183-
184-
It's also possible you don't even want to define a [`loader`](../../start/data/route-object#loader)
185-
implementation at the route level. Maybe you want to just determine the
186-
routes and issue a single GraphQL request for all of your data? You can do
187-
that by setting your `route.loader=true` so it qualifies as "having a
188-
loader", and then store GQL fragments on `route.handle`:
189-
190-
```ts
191-
const routes = [
192-
{
193-
id: "parent",
194-
path: "/parent",
195-
loader: true,
196-
handle: {
197-
gql: gql`
198-
fragment Parent on Whatever {
199-
parentField
200-
}
201-
`,
202-
},
203-
children: [
204-
{
205-
id: "child",
206-
path: "child",
207-
loader: true,
208-
handle: {
209-
gql: gql`
210-
fragment Child on Whatever {
211-
childField
212-
}
213-
`,
214-
},
215-
},
216-
],
217-
},
218-
];
219-
220-
let router = createBrowserRouter(routes, {
221-
async dataStrategy({ matches, params, request }) {
222-
// Compose route fragments into a single GQL payload
223-
let gql = getFragmentsFromRouteHandles(matches);
224-
let data = await fetchGql(gql);
225-
// Parse results back out into individual route level `DataStrategyResult`'s
226-
// keyed by `routeId`
227-
let results = parseResultsFromGql(data);
22872
return results;
22973
},
23074
});
23175
```
232-
</details>
23376

23477
### opts.future
23578

@@ -336,7 +179,7 @@ individual routes prior to router initialization (and on any subsequently
336179
added routes via `route.lazy` or `patchRoutesOnNavigation`). This is
337180
mostly useful for observability such as wrapping navigations, fetches,
338181
as well as route loaders/actions/middlewares with logging and/or performance
339-
tracing.
182+
tracing. See the [docs](../../how-to/instrumentation) for more information.
340183

341184
```tsx
342185
let router = createBrowserRouter(routes, {

0 commit comments

Comments
 (0)