@@ -555,9 +555,9 @@ export function createRouter(init: RouterInit): Router {
555
555
restoreScrollPosition : null ,
556
556
preventScrollReset : false ,
557
557
revalidation : "idle" ,
558
- loaderData : init . hydrationData ?. loaderData || { } ,
559
- actionData : init . hydrationData ?. actionData || null ,
560
- errors : init . hydrationData ?. errors || initialErrors ,
558
+ loaderData : ( init . hydrationData && init . hydrationData . loaderData ) || { } ,
559
+ actionData : ( init . hydrationData && init . hydrationData . actionData ) || null ,
560
+ errors : ( init . hydrationData && init . hydrationData . errors ) || initialErrors ,
561
561
fetchers : new Map ( ) ,
562
562
} ;
563
563
@@ -628,7 +628,7 @@ export function createRouter(init: RouterInit): Router {
628
628
unlistenHistory ( ) ;
629
629
}
630
630
subscribers . clear ( ) ;
631
- pendingNavigationController ? .abort ( ) ;
631
+ pendingNavigationController && pendingNavigationController . abort ( ) ;
632
632
state . fetchers . forEach ( ( _ , key ) => deleteFetcher ( key ) ) ;
633
633
}
634
634
@@ -731,9 +731,9 @@ export function createRouter(init: RouterInit): Router {
731
731
732
732
let { path, submission, error } = normalizeNavigateOptions ( to , opts ) ;
733
733
734
- let location = createLocation ( state . location , path , opts ? .state ) ;
734
+ let location = createLocation ( state . location , path , opts && opts . state ) ;
735
735
let historyAction =
736
- opts ? .replace === true || submission != null
736
+ ( opts && opts . replace ) === true || submission != null
737
737
? HistoryAction . Replace
738
738
: HistoryAction . Push ;
739
739
let preventScrollReset =
@@ -747,7 +747,7 @@ export function createRouter(init: RouterInit): Router {
747
747
// render at the right error boundary after we match routes
748
748
pendingError : error ,
749
749
preventScrollReset,
750
- replace : opts ? .replace ,
750
+ replace : opts && opts . replace ,
751
751
} ) ;
752
752
}
753
753
@@ -802,17 +802,18 @@ export function createRouter(init: RouterInit): Router {
802
802
// Abort any in-progress navigations and start a new one. Unset any ongoing
803
803
// uninterrupted revalidations unless told otherwise, since we want this
804
804
// new navigation to update history normally
805
- pendingNavigationController ? .abort ( ) ;
805
+ pendingNavigationController && pendingNavigationController . abort ( ) ;
806
806
pendingNavigationController = null ;
807
807
pendingAction = historyAction ;
808
- isUninterruptedRevalidation = opts ?. startUninterruptedRevalidation === true ;
808
+ isUninterruptedRevalidation =
809
+ ( opts && opts . startUninterruptedRevalidation ) === true ;
809
810
810
811
// Save the current scroll position every time we start a new navigation,
811
812
// and track whether we should reset scroll on completion
812
813
saveScrollPosition ( state . location , state . matches ) ;
813
- pendingPreventScrollReset = opts ? .preventScrollReset === true ;
814
+ pendingPreventScrollReset = ( opts && opts . preventScrollReset ) === true ;
814
815
815
- let loadingNavigation = opts ? .overrideNavigation ;
816
+ let loadingNavigation = opts && opts . overrideNavigation ;
816
817
let matches = matchRoutes ( dataRoutes , location , init . basename ) ;
817
818
818
819
// Short circuit with a 404 on the root error boundary if we match nothing
@@ -845,20 +846,20 @@ export function createRouter(init: RouterInit): Router {
845
846
let request = createRequest (
846
847
location ,
847
848
pendingNavigationController . signal ,
848
- opts ? .submission
849
+ opts && opts . submission
849
850
) ;
850
851
let pendingActionData : RouteData | undefined ;
851
852
let pendingError : RouteData | undefined ;
852
853
853
- if ( opts ? .pendingError ) {
854
+ if ( opts && opts . pendingError ) {
854
855
// If we have a pendingError, it means the user attempted a GET submission
855
856
// with binary FormData so assign here and skip to handleLoaders. That
856
857
// way we handle calling loaders above the boundary etc. It's not really
857
858
// different from an actionError in that sense.
858
859
pendingError = {
859
860
[ findNearestBoundary ( matches ) . route . id ] : opts . pendingError ,
860
861
} ;
861
- } else if ( opts ? .submission ) {
862
+ } else if ( opts && opts . submission ) {
862
863
// Call action if we received an action submission
863
864
let actionOutput = await handleAction (
864
865
request ,
@@ -889,8 +890,8 @@ export function createRouter(init: RouterInit): Router {
889
890
location ,
890
891
matches ,
891
892
loadingNavigation ,
892
- opts ? .submission ,
893
- opts ? .replace ,
893
+ opts && opts . submission ,
894
+ opts && opts . replace ,
894
895
pendingActionData ,
895
896
pendingError
896
897
) ;
@@ -950,7 +951,11 @@ export function createRouter(init: RouterInit): Router {
950
951
location : createLocation ( state . location , result . location ) ,
951
952
...submission ,
952
953
} ;
953
- await startRedirectNavigation ( result , redirectNavigation , opts ?. replace ) ;
954
+ await startRedirectNavigation (
955
+ result ,
956
+ redirectNavigation ,
957
+ opts && opts . replace
958
+ ) ;
954
959
return { shortCircuited : true } ;
955
960
}
956
961
@@ -963,7 +968,7 @@ export function createRouter(init: RouterInit): Router {
963
968
// action threw an error that'll be rendered in an errorElement, we fall
964
969
// back to PUSH so that the user can use the back button to get back to
965
970
// the pre-submission form location to try again
966
- if ( opts ? .replace !== true ) {
971
+ if ( ( opts && opts . replace ) !== true ) {
967
972
pendingAction = HistoryAction . Push ;
968
973
}
969
974
@@ -1025,8 +1030,8 @@ export function createRouter(init: RouterInit): Router {
1025
1030
// already cancelled all pending deferreds so this would be a no-op
1026
1031
cancelActiveDeferreds (
1027
1032
( routeId ) =>
1028
- ! matches ? .some ( ( m ) => m . route . id === routeId ) ||
1029
- matchesToLoad ? .some ( ( m ) => m . route . id === routeId )
1033
+ ! ( matches && matches . some ( ( m ) => m . route . id === routeId ) ) ||
1034
+ ( matchesToLoad && matchesToLoad . some ( ( m ) => m . route . id === routeId ) )
1030
1035
) ;
1031
1036
1032
1037
// Short circuit if we have no loaders to run
@@ -1047,9 +1052,10 @@ export function createRouter(init: RouterInit): Router {
1047
1052
// a revalidation interrupting an actionReload)
1048
1053
if ( ! isUninterruptedRevalidation ) {
1049
1054
revalidatingFetchers . forEach ( ( [ key ] ) => {
1055
+ const fetcher = state . fetchers . get ( key ) ;
1050
1056
let revalidatingFetcher : FetcherStates [ "Loading" ] = {
1051
1057
state : "loading" ,
1052
- data : state . fetchers . get ( key ) ? .data ,
1058
+ data : fetcher && fetcher . data ,
1053
1059
formMethod : undefined ,
1054
1060
formAction : undefined ,
1055
1061
formEncType : undefined ,
@@ -1192,10 +1198,11 @@ export function createRouter(init: RouterInit): Router {
1192
1198
}
1193
1199
1194
1200
// Put this fetcher into it's submitting state
1201
+ let existingFetcher = state . fetchers . get ( key ) ;
1195
1202
let fetcher : FetcherStates [ "Submitting" ] = {
1196
1203
state : "submitting" ,
1197
1204
...submission ,
1198
- data : state . fetchers . get ( key ) ?. data || undefined ,
1205
+ data : existingFetcher && existingFetcher . data ,
1199
1206
} ;
1200
1207
state . fetchers . set ( key , fetcher ) ;
1201
1208
updateState ( { fetchers : new Map ( state . fetchers ) } ) ;
@@ -1289,9 +1296,10 @@ export function createRouter(init: RouterInit): Router {
1289
1296
revalidatingFetchers
1290
1297
. filter ( ( [ staleKey ] ) => staleKey !== key )
1291
1298
. forEach ( ( [ staleKey ] ) => {
1299
+ let existingFetcher = state . fetchers . get ( staleKey ) ;
1292
1300
let revalidatingFetcher : FetcherStates [ "Loading" ] = {
1293
1301
state : "loading" ,
1294
- data : state . fetchers . get ( staleKey ) ? .data ,
1302
+ data : existingFetcher && existingFetcher . data ,
1295
1303
formMethod : undefined ,
1296
1304
formAction : undefined ,
1297
1305
formEncType : undefined ,
@@ -1360,7 +1368,7 @@ export function createRouter(init: RouterInit): Router {
1360
1368
loadId > pendingNavigationLoadId
1361
1369
) {
1362
1370
invariant ( pendingAction , "Expected pending action" ) ;
1363
- pendingNavigationController ? .abort ( ) ;
1371
+ pendingNavigationController && pendingNavigationController . abort ( ) ;
1364
1372
1365
1373
completeNavigation ( state . navigation . location , {
1366
1374
matches,
@@ -1388,14 +1396,15 @@ export function createRouter(init: RouterInit): Router {
1388
1396
path : string ,
1389
1397
match : AgnosticDataRouteMatch
1390
1398
) {
1399
+ let existingFetcher = state . fetchers . get ( key ) ;
1391
1400
// Put this fetcher into it's loading state
1392
1401
let loadingFetcher : FetcherStates [ "Loading" ] = {
1393
1402
state : "loading" ,
1394
1403
formMethod : undefined ,
1395
1404
formAction : undefined ,
1396
1405
formEncType : undefined ,
1397
1406
formData : undefined ,
1398
- data : state . fetchers . get ( key ) ?. data || undefined ,
1407
+ data : existingFetcher && existingFetcher . data ,
1399
1408
} ;
1400
1409
state . fetchers . set ( key , loadingFetcher ) ;
1401
1410
updateState ( { fetchers : new Map ( state . fetchers ) } ) ;
@@ -2109,7 +2118,8 @@ function normalizeNavigateOptions(
2109
2118
submission : {
2110
2119
formMethod : opts . formMethod ,
2111
2120
formAction : createHref ( parsePath ( path ) ) ,
2112
- formEncType : opts ?. formEncType || "application/x-www-form-urlencoded" ,
2121
+ formEncType :
2122
+ ( opts && opts . formEncType ) || "application/x-www-form-urlencoded" ,
2113
2123
formData : opts . formData ,
2114
2124
} ,
2115
2125
} ;
@@ -2211,25 +2221,26 @@ function getMatchesToLoad(
2211
2221
2212
2222
// Pick fetcher.loads that need to be revalidated
2213
2223
let revalidatingFetchers : RevalidatingFetcher [ ] = [ ] ;
2214
- fetchLoadMatches ?. forEach ( ( [ href , match ] , key ) => {
2215
- // This fetcher was cancelled from a prior action submission - force reload
2216
- if ( cancelledFetcherLoads . includes ( key ) ) {
2217
- revalidatingFetchers . push ( [ key , href , match ] ) ;
2218
- } else if ( isRevalidationRequired ) {
2219
- let shouldRevalidate = shouldRevalidateLoader (
2220
- href ,
2221
- match ,
2222
- submission ,
2223
- href ,
2224
- match ,
2225
- isRevalidationRequired ,
2226
- actionResult
2227
- ) ;
2228
- if ( shouldRevalidate ) {
2224
+ fetchLoadMatches &&
2225
+ fetchLoadMatches . forEach ( ( [ href , match ] , key ) => {
2226
+ // This fetcher was cancelled from a prior action submission - force reload
2227
+ if ( cancelledFetcherLoads . includes ( key ) ) {
2229
2228
revalidatingFetchers . push ( [ key , href , match ] ) ;
2229
+ } else if ( isRevalidationRequired ) {
2230
+ let shouldRevalidate = shouldRevalidateLoader (
2231
+ href ,
2232
+ match ,
2233
+ submission ,
2234
+ href ,
2235
+ match ,
2236
+ isRevalidationRequired ,
2237
+ actionResult
2238
+ ) ;
2239
+ if ( shouldRevalidate ) {
2240
+ revalidatingFetchers . push ( [ key , href , match ] ) ;
2241
+ }
2230
2242
}
2231
- }
2232
- } ) ;
2243
+ } ) ;
2233
2244
2234
2245
return [ navigationMatches , revalidatingFetchers ] ;
2235
2246
}
@@ -2257,12 +2268,14 @@ function isNewRouteInstance(
2257
2268
currentMatch : AgnosticDataRouteMatch ,
2258
2269
match : AgnosticDataRouteMatch
2259
2270
) {
2271
+ let currentPath = currentMatch . route . path ;
2260
2272
return (
2261
2273
// param change for this match, /users/123 -> /users/456
2262
2274
currentMatch . pathname !== match . pathname ||
2263
2275
// splat param changed, which is not present in match.path
2264
2276
// e.g. /files/images/avatar.jpg -> files/finances.xls
2265
- ( currentMatch . route . path ?. endsWith ( "*" ) &&
2277
+ ( currentPath &&
2278
+ currentPath . endsWith ( "*" ) &&
2266
2279
currentMatch . params [ "*" ] !== match . params [ "*" ] )
2267
2280
) ;
2268
2281
}
@@ -2375,7 +2388,8 @@ async function callLoaderOrAction(
2375
2388
}
2376
2389
2377
2390
let data : any ;
2378
- if ( result . headers . get ( "Content-Type" ) ?. startsWith ( "application/json" ) ) {
2391
+ let contentType = result . headers . get ( "Content-Type" ) ;
2392
+ if ( contentType && contentType . startsWith ( "application/json" ) ) {
2379
2393
data = await result . json ( ) ;
2380
2394
} else {
2381
2395
data = await result . text ( ) ;
@@ -2497,7 +2511,7 @@ function processRouteLoaderData(
2497
2511
loaderHeaders [ id ] = result . headers ;
2498
2512
}
2499
2513
} else if ( isDeferredResult ( result ) ) {
2500
- activeDeferreds ? .set ( id , result . deferredData ) ;
2514
+ activeDeferreds && activeDeferreds . set ( id , result . deferredData ) ;
2501
2515
loaderData [ id ] = result . deferredData . data ;
2502
2516
// TODO: Add statusCode/headers once we wire up streaming in Remix
2503
2517
} else {
@@ -2560,7 +2574,7 @@ function processLoaderData(
2560
2574
// Process fetcher non-redirect errors
2561
2575
if ( isErrorResult ( result ) ) {
2562
2576
let boundaryMatch = findNearestBoundary ( state . matches , match . route . id ) ;
2563
- if ( ! errors ?. [ boundaryMatch . route . id ] ) {
2577
+ if ( ! ( errors && errors [ boundaryMatch . route . id ] ) ) {
2564
2578
errors = {
2565
2579
...errors ,
2566
2580
[ boundaryMatch . route . id ] : result . error ,
@@ -2695,7 +2709,7 @@ function isErrorResult(result: DataResult): result is ErrorResult {
2695
2709
}
2696
2710
2697
2711
function isRedirectResult ( result ?: DataResult ) : result is RedirectResult {
2698
- return result ? .type === ResultType . redirect ;
2712
+ return ( result && result . type ) === ResultType . redirect ;
2699
2713
}
2700
2714
2701
2715
async function resolveDeferredResults (
@@ -2715,7 +2729,7 @@ async function resolveDeferredResults(
2715
2729
let isRevalidatingLoader =
2716
2730
currentMatch != null &&
2717
2731
! isNewRouteInstance ( currentMatch , match ) &&
2718
- currentLoaderData ?. [ match . route . id ] !== undefined ;
2732
+ ( currentLoaderData && currentLoaderData [ match . route . id ] ) !== undefined ;
2719
2733
2720
2734
if ( isDeferredResult ( result ) && ( isFetcher || isRevalidatingLoader ) ) {
2721
2735
// Note: we do not have to touch activeDeferreds here since we race them
0 commit comments