@@ -36,9 +36,22 @@ export type SingleFetchResults = {
36
36
} ;
37
37
38
38
export function getSingleFetchDataStrategy (
39
- responseStubs : ReturnType < typeof getResponseStubs >
39
+ responseStubs : ReturnType < typeof getResponseStubs > ,
40
+ {
41
+ isActionDataRequest,
42
+ loadRouteIds,
43
+ } : { isActionDataRequest ?: boolean ; loadRouteIds ?: string [ ] } = { }
40
44
) {
41
45
return async ( { request, matches } : DataStrategyFunctionArgs ) => {
46
+ // Don't call loaders on action data requests
47
+ if ( isActionDataRequest && request . method === "GET" ) {
48
+ return await Promise . all (
49
+ matches . map ( ( m ) =>
50
+ m . resolve ( async ( ) => ( { type : "data" , result : null } ) )
51
+ )
52
+ ) ;
53
+ }
54
+
42
55
let results = await Promise . all (
43
56
matches . map ( async ( match ) => {
44
57
let responseStub : ResponseStub | undefined ;
@@ -49,7 +62,11 @@ export function getSingleFetchDataStrategy(
49
62
}
50
63
51
64
let result = await match . resolve ( async ( handler ) => {
52
- let data = await handler ( { response : responseStub } ) ;
65
+ // Only run opt-in loaders when fine-grained revalidation is enabled
66
+ let data =
67
+ loadRouteIds && ! loadRouteIds . includes ( match . route . id )
68
+ ? null
69
+ : await handler ( { response : responseStub } ) ;
53
70
return { type : "data" , result : data } ;
54
71
} ) ;
55
72
@@ -96,8 +113,9 @@ export async function singleFetchAction(
96
113
let result = await staticHandler . query ( handlerRequest , {
97
114
requestContext : loadContext ,
98
115
skipLoaderErrorBubbling : true ,
99
- skipLoaders : true ,
100
- unstable_dataStrategy : getSingleFetchDataStrategy ( responseStubs ) ,
116
+ unstable_dataStrategy : getSingleFetchDataStrategy ( responseStubs , {
117
+ isActionDataRequest : true ,
118
+ } ) ,
101
119
} ) ;
102
120
103
121
// Unlike `handleDataRequest`, when singleFetch is enabled, queryRoute does
@@ -113,7 +131,9 @@ export async function singleFetchAction(
113
131
let context = result ;
114
132
115
133
let singleFetchResult : SingleFetchResult ;
116
- let { statusCode, headers } = mergeResponseStubs ( context , responseStubs ) ;
134
+ let { statusCode, headers } = mergeResponseStubs ( context , responseStubs , {
135
+ isActionDataRequest : true ,
136
+ } ) ;
117
137
118
138
if ( isRedirectStatusCode ( statusCode ) && headers . has ( "Location" ) ) {
119
139
return {
@@ -176,9 +196,10 @@ export async function singleFetchLoaders(
176
196
let responseStubs = getResponseStubs ( ) ;
177
197
let result = await staticHandler . query ( handlerRequest , {
178
198
requestContext : loadContext ,
179
- loadRouteIds,
180
199
skipLoaderErrorBubbling : true ,
181
- unstable_dataStrategy : getSingleFetchDataStrategy ( responseStubs ) ,
200
+ unstable_dataStrategy : getSingleFetchDataStrategy ( responseStubs , {
201
+ loadRouteIds,
202
+ } ) ,
182
203
} ) ;
183
204
184
205
if ( isResponse ( result ) ) {
@@ -323,17 +344,20 @@ function proxyResponseToResponseStub(
323
344
324
345
export function mergeResponseStubs (
325
346
context : StaticHandlerContext ,
326
- responseStubs : ReturnType < typeof getResponseStubs >
347
+ responseStubs : ReturnType < typeof getResponseStubs > ,
348
+ { isActionDataRequest } : { isActionDataRequest ?: boolean } = { }
327
349
) {
328
350
let statusCode : number | undefined = undefined ;
329
351
let headers = new Headers ( ) ;
330
352
331
353
// Action followed by top-down loaders
332
354
let actionStub = responseStubs [ ResponseStubActionSymbol ] ;
333
- let stubs = [
334
- actionStub ,
335
- ...context . matches . map ( ( m ) => responseStubs [ m . route . id ] ) ,
336
- ] ;
355
+ let stubs = [ actionStub ] ;
356
+
357
+ // Nothing to merge at the route level on action data requests
358
+ if ( ! isActionDataRequest ) {
359
+ stubs . push ( ...context . matches . map ( ( m ) => responseStubs [ m . route . id ] ) ) ;
360
+ }
337
361
338
362
for ( let stub of stubs ) {
339
363
// Take the highest error/redirect, or the lowest success value - preferring
0 commit comments