Skip to content

Commit 1058a37

Browse files
authored
Minor updates for single fetch headers behavior (#11377)
1 parent 12afb2e commit 1058a37

File tree

4 files changed

+90
-32
lines changed

4 files changed

+90
-32
lines changed

.changeset/slow-flies-help.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"@remix-run/router": minor
3+
---
4+
5+
- Move `unstable_dataStrategy` from `createStaticHandler` to `staticHandler.query` so it can be request-specific for use with the `ResponseStub` approach in Remix. It's not really applicable to `queryRoute` for now since that's a singular handler call anyway so any pre-processing/post/processing could be done there manually.
6+
- Added a new `skipLoaders` flag to `staticHandler.query` for calling only the action in Remix Single Fetch

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@
105105
},
106106
"filesize": {
107107
"packages/router/dist/router.umd.min.js": {
108-
"none": "52.4 kB"
108+
"none": "52.8 kB"
109109
},
110110
"packages/react-router/dist/react-router.production.min.js": {
111111
"none": "14.8 kB"

packages/router/__tests__/ssr-test.ts

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1649,11 +1649,11 @@ describe("ssr", () => {
16491649

16501650
describe("router dataStrategy", () => {
16511651
it("should support document load navigations with custom dataStrategy", async () => {
1652-
let { query } = createStaticHandler(SSR_ROUTES, {
1652+
let { query } = createStaticHandler(SSR_ROUTES);
1653+
1654+
let context = await query(createRequest("/custom"), {
16531655
unstable_dataStrategy: urlDataStrategy,
16541656
});
1655-
1656-
let context = await query(createRequest("/custom"));
16571657
expect(context).toMatchObject({
16581658
actionData: null,
16591659
loaderData: {
@@ -2678,18 +2678,5 @@ describe("ssr", () => {
26782678

26792679
/* eslint-enable jest/no-conditional-expect */
26802680
});
2681-
2682-
describe("router dataStrategy", () => {
2683-
it("should match routes automatically if no routeId is provided", async () => {
2684-
let { queryRoute } = createStaticHandler(SSR_ROUTES, {
2685-
unstable_dataStrategy: urlDataStrategy,
2686-
});
2687-
let data;
2688-
2689-
data = await queryRoute(createRequest("/custom"));
2690-
expect(data).toBeInstanceOf(URLSearchParams);
2691-
expect((data as URLSearchParams).get("foo")).toBe("bar");
2692-
});
2693-
});
26942681
});
26952682
});

packages/router/router.ts

Lines changed: 80 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -407,7 +407,9 @@ export interface StaticHandler {
407407
opts?: {
408408
loadRouteIds?: string[];
409409
requestContext?: unknown;
410+
skipLoaders?: boolean;
410411
skipLoaderErrorBubbling?: boolean;
412+
unstable_dataStrategy?: DataStrategyFunction;
411413
}
412414
): Promise<StaticHandlerContext | Response>;
413415
queryRoute(
@@ -2926,7 +2928,6 @@ export interface CreateStaticHandlerOptions {
29262928
* @deprecated Use `mapRouteProperties` instead
29272929
*/
29282930
detectErrorBoundary?: DetectErrorBoundaryFunction;
2929-
unstable_dataStrategy?: DataStrategyFunction;
29302931
mapRouteProperties?: MapRoutePropertiesFunction;
29312932
future?: Partial<StaticHandlerFutureConfig>;
29322933
}
@@ -2942,7 +2943,6 @@ export function createStaticHandler(
29422943

29432944
let manifest: RouteManifest = {};
29442945
let basename = (opts ? opts.basename : null) || "/";
2945-
let dataStrategyImpl = opts?.unstable_dataStrategy || defaultDataStrategy;
29462946
let mapRouteProperties: MapRoutePropertiesFunction;
29472947
if (opts?.mapRouteProperties) {
29482948
mapRouteProperties = opts.mapRouteProperties;
@@ -2988,25 +2988,31 @@ export function createStaticHandler(
29882988
* propagate that out and return the raw Response so the HTTP server can
29892989
* return it directly.
29902990
*
2991-
* - `opts.loadRouteIds` is an optional array of routeIds if you wish to only
2992-
* run a subset of route loaders on a GET request
2991+
* - `opts.loadRouteIds` is an optional array of routeIds to run only a subset of
2992+
* loaders during a query() call
29932993
* - `opts.requestContext` is an optional server context that will be passed
29942994
* to actions/loaders in the `context` parameter
29952995
* - `opts.skipLoaderErrorBubbling` is an optional parameter that will prevent
2996-
* the bubbling of loader errors which allows single-fetch-type implementations
2996+
* the bubbling of errors which allows single-fetch-type implementations
29972997
* where the client will handle the bubbling and we may need to return data
29982998
* for the handling route
2999+
* - `opts.skipLoaders` is an optional parameter that will prevent loaders
3000+
* from running after an action
29993001
*/
30003002
async function query(
30013003
request: Request,
30023004
{
30033005
loadRouteIds,
30043006
requestContext,
30053007
skipLoaderErrorBubbling,
3008+
skipLoaders,
3009+
unstable_dataStrategy,
30063010
}: {
30073011
loadRouteIds?: string[];
30083012
requestContext?: unknown;
30093013
skipLoaderErrorBubbling?: boolean;
3014+
skipLoaders?: boolean;
3015+
unstable_dataStrategy?: DataStrategyFunction;
30103016
} = {}
30113017
): Promise<StaticHandlerContext | Response> {
30123018
let url = new URL(request.url);
@@ -3058,8 +3064,10 @@ export function createStaticHandler(
30583064
location,
30593065
matches,
30603066
requestContext,
3067+
unstable_dataStrategy || null,
30613068
loadRouteIds || null,
30623069
skipLoaderErrorBubbling === true,
3070+
skipLoaders === true,
30633071
null
30643072
);
30653073
if (isResponse(result)) {
@@ -3137,6 +3145,8 @@ export function createStaticHandler(
31373145
matches,
31383146
requestContext,
31393147
null,
3148+
null,
3149+
false,
31403150
false,
31413151
match
31423152
);
@@ -3174,8 +3184,10 @@ export function createStaticHandler(
31743184
location: Location,
31753185
matches: AgnosticDataRouteMatch[],
31763186
requestContext: unknown,
3187+
unstable_dataStrategy: DataStrategyFunction | null,
31773188
loadRouteIds: string[] | null,
31783189
skipLoaderErrorBubbling: boolean,
3190+
skipLoaders: boolean,
31793191
routeMatch: AgnosticDataRouteMatch | null
31803192
): Promise<Omit<StaticHandlerContext, "location" | "basename"> | Response> {
31813193
invariant(
@@ -3190,8 +3202,10 @@ export function createStaticHandler(
31903202
matches,
31913203
routeMatch || getTargetMatch(matches, location),
31923204
requestContext,
3205+
unstable_dataStrategy,
31933206
loadRouteIds,
31943207
skipLoaderErrorBubbling,
3208+
skipLoaders,
31953209
routeMatch != null
31963210
);
31973211
return result;
@@ -3201,6 +3215,7 @@ export function createStaticHandler(
32013215
request,
32023216
matches,
32033217
requestContext,
3218+
unstable_dataStrategy,
32043219
loadRouteIds,
32053220
skipLoaderErrorBubbling,
32063221
routeMatch
@@ -3236,8 +3251,10 @@ export function createStaticHandler(
32363251
matches: AgnosticDataRouteMatch[],
32373252
actionMatch: AgnosticDataRouteMatch,
32383253
requestContext: unknown,
3254+
unstable_dataStrategy: DataStrategyFunction | null,
32393255
loadRouteIds: string[] | null,
32403256
skipLoaderErrorBubbling: boolean,
3257+
skipLoaders: boolean,
32413258
isRouteRequest: boolean
32423259
): Promise<Omit<StaticHandlerContext, "location" | "basename"> | Response> {
32433260
let result: DataResult;
@@ -3262,7 +3279,8 @@ export function createStaticHandler(
32623279
[actionMatch],
32633280
matches,
32643281
isRouteRequest,
3265-
requestContext
3282+
requestContext,
3283+
unstable_dataStrategy
32663284
);
32673285
result = results[0];
32683286

@@ -3326,11 +3344,38 @@ export function createStaticHandler(
33263344
if (isErrorResult(result)) {
33273345
// Store off the pending error - we use it to determine which loaders
33283346
// to call and will commit it when we complete the navigation
3329-
let boundaryMatch = findNearestBoundary(matches, actionMatch.route.id);
3347+
let boundaryMatch = skipLoaderErrorBubbling
3348+
? actionMatch
3349+
: findNearestBoundary(matches, actionMatch.route.id);
3350+
let statusCode = isRouteErrorResponse(result.error)
3351+
? result.error.status
3352+
: result.statusCode != null
3353+
? result.statusCode
3354+
: 500;
3355+
let actionHeaders = {
3356+
...(result.headers ? { [actionMatch.route.id]: result.headers } : {}),
3357+
};
3358+
3359+
if (skipLoaders) {
3360+
return {
3361+
matches,
3362+
loaderData: {},
3363+
actionData: {},
3364+
errors: {
3365+
[boundaryMatch.route.id]: result.error,
3366+
},
3367+
statusCode,
3368+
loaderHeaders: {},
3369+
actionHeaders,
3370+
activeDeferreds: null,
3371+
};
3372+
}
3373+
33303374
let context = await loadRouteData(
33313375
loaderRequest,
33323376
matches,
33333377
requestContext,
3378+
unstable_dataStrategy,
33343379
loadRouteIds,
33353380
skipLoaderErrorBubbling,
33363381
null,
@@ -3340,20 +3385,36 @@ export function createStaticHandler(
33403385
// action status codes take precedence over loader status codes
33413386
return {
33423387
...context,
3343-
statusCode: isRouteErrorResponse(result.error)
3344-
? result.error.status
3345-
: 500,
3388+
statusCode,
33463389
actionData: null,
3347-
actionHeaders: {
3348-
...(result.headers ? { [actionMatch.route.id]: result.headers } : {}),
3390+
actionHeaders,
3391+
};
3392+
}
3393+
3394+
let actionHeaders = result.headers
3395+
? { [actionMatch.route.id]: result.headers }
3396+
: {};
3397+
3398+
if (skipLoaders) {
3399+
return {
3400+
matches,
3401+
loaderData: {},
3402+
actionData: {
3403+
[actionMatch.route.id]: result.data,
33493404
},
3405+
errors: null,
3406+
statusCode: result.statusCode || 200,
3407+
loaderHeaders: {},
3408+
actionHeaders,
3409+
activeDeferreds: null,
33503410
};
33513411
}
33523412

33533413
let context = await loadRouteData(
33543414
loaderRequest,
33553415
matches,
33563416
requestContext,
3417+
unstable_dataStrategy,
33573418
loadRouteIds,
33583419
skipLoaderErrorBubbling,
33593420
null
@@ -3376,6 +3437,7 @@ export function createStaticHandler(
33763437
request: Request,
33773438
matches: AgnosticDataRouteMatch[],
33783439
requestContext: unknown,
3440+
unstable_dataStrategy: DataStrategyFunction | null,
33793441
loadRouteIds: string[] | null,
33803442
skipLoaderErrorBubbling: boolean,
33813443
routeMatch: AgnosticDataRouteMatch | null,
@@ -3444,7 +3506,8 @@ export function createStaticHandler(
34443506
matchesToLoad,
34453507
matches,
34463508
isRouteRequest,
3447-
requestContext
3509+
requestContext,
3510+
unstable_dataStrategy
34483511
);
34493512

34503513
if (request.signal.aborted) {
@@ -3490,10 +3553,11 @@ export function createStaticHandler(
34903553
matchesToLoad: AgnosticDataRouteMatch[],
34913554
matches: AgnosticDataRouteMatch[],
34923555
isRouteRequest: boolean,
3493-
requestContext: unknown
3556+
requestContext: unknown,
3557+
unstable_dataStrategy: DataStrategyFunction | null
34943558
): Promise<DataResult[]> {
34953559
let results = await callDataStrategyImpl(
3496-
dataStrategyImpl,
3560+
unstable_dataStrategy || defaultDataStrategy,
34973561
type,
34983562
request,
34993563
matchesToLoad,
@@ -4188,6 +4252,7 @@ async function callDataStrategyImpl(
41884252
}),
41894253
request,
41904254
params: matches[0].params,
4255+
context: requestContext,
41914256
});
41924257

41934258
// Throw if any loadRoute implementations not called since they are what

0 commit comments

Comments
 (0)