@@ -524,6 +524,7 @@ type BaseNavigateOrFetchOptions = {
524524 preventScrollReset ?: boolean ;
525525 relative ?: RelativeRoutingType ;
526526 flushSync ?: boolean ;
527+ shouldRevalidate ?: boolean | ( ( ) => boolean ) ;
527528} ;
528529
529530// Only allowed for navigations
@@ -1548,6 +1549,14 @@ export function createRouter(init: RouterInit): Router {
15481549 return ;
15491550 }
15501551
1552+ let shouldRevalidate =
1553+ opts && "shouldRevalidate" in opts
1554+ ? typeof opts . shouldRevalidate === "function"
1555+ ? opts . shouldRevalidate ( )
1556+ : // undefined should eval to true
1557+ opts . shouldRevalidate !== false
1558+ : true ;
1559+
15511560 await startNavigation ( historyAction , nextLocation , {
15521561 submission,
15531562 // Send through the formData serialization error if we have one so we can
@@ -1556,6 +1565,7 @@ export function createRouter(init: RouterInit): Router {
15561565 preventScrollReset,
15571566 replace : opts && opts . replace ,
15581567 enableViewTransition : opts && opts . viewTransition ,
1568+ shouldRevalidate,
15591569 flushSync,
15601570 } ) ;
15611571 }
@@ -1632,6 +1642,7 @@ export function createRouter(init: RouterInit): Router {
16321642 replace ?: boolean ;
16331643 enableViewTransition ?: boolean ;
16341644 flushSync ?: boolean ;
1645+ shouldRevalidate ?: boolean ;
16351646 } ,
16361647 ) : Promise < void > {
16371648 // Abort any in-progress navigations and start a new one. Unset any ongoing
@@ -1771,6 +1782,15 @@ export function createRouter(init: RouterInit): Router {
17711782
17721783 matches = actionResult . matches || matches ;
17731784 pendingActionResult = actionResult . pendingActionResult ;
1785+
1786+ if ( opts . shouldRevalidate === false ) {
1787+ completeNavigation ( location , {
1788+ matches,
1789+ ...getActionDataForCommit ( pendingActionResult ) ,
1790+ } ) ;
1791+ return ;
1792+ }
1793+
17741794 loadingNavigation = getLoadingNavigation ( location , opts . submission ) ;
17751795 flushSync = false ;
17761796 // No need to do fog of war matching again on loader execution
@@ -2346,6 +2366,13 @@ export function createRouter(init: RouterInit): Router {
23462366 let preventScrollReset = ( opts && opts . preventScrollReset ) === true ;
23472367
23482368 if ( submission && isMutationMethod ( submission . formMethod ) ) {
2369+ let shouldRevalidate =
2370+ opts && "shouldRevalidate" in opts
2371+ ? typeof opts . shouldRevalidate === "function"
2372+ ? opts . shouldRevalidate ( )
2373+ : // undefined should eval to true
2374+ opts . shouldRevalidate !== false
2375+ : true ;
23492376 await handleFetcherAction (
23502377 key ,
23512378 routeId ,
@@ -2356,6 +2383,7 @@ export function createRouter(init: RouterInit): Router {
23562383 flushSync ,
23572384 preventScrollReset ,
23582385 submission ,
2386+ shouldRevalidate ,
23592387 ) ;
23602388 return ;
23612389 }
@@ -2388,6 +2416,7 @@ export function createRouter(init: RouterInit): Router {
23882416 flushSync : boolean ,
23892417 preventScrollReset : boolean ,
23902418 submission : Submission ,
2419+ shouldRevalidate : boolean ,
23912420 ) {
23922421 interruptActiveLoads ( ) ;
23932422 fetchLoadMatches . delete ( key ) ;
@@ -2563,6 +2592,7 @@ export function createRouter(init: RouterInit): Router {
25632592 basename ,
25642593 init . patchRoutesOnNavigation != null ,
25652594 [ match . route . id , actionResult ] ,
2595+ shouldRevalidate ,
25662596 ) ;
25672597
25682598 // Put all revalidating fetchers into the loading state, except for the
@@ -2594,6 +2624,15 @@ export function createRouter(init: RouterInit): Router {
25942624 abortPendingFetchRevalidations ,
25952625 ) ;
25962626
2627+ if ( ! shouldRevalidate ) {
2628+ if ( state . fetchers . has ( key ) ) {
2629+ let doneFetcher = getDoneFetcher ( actionResult . data ) ;
2630+ state . fetchers . set ( key , doneFetcher ) ;
2631+ }
2632+ fetchControllers . delete ( key ) ;
2633+ return ;
2634+ }
2635+
25972636 let { loaderResults, fetcherResults } =
25982637 await callLoadersAndMaybeResolveData (
25992638 dsMatches ,
@@ -4820,6 +4859,7 @@ function getMatchesToLoad(
48204859 basename : string | undefined ,
48214860 hasPatchRoutesOnNavigation : boolean ,
48224861 pendingActionResult ?: PendingActionResult ,
4862+ shouldRevalidate ?: boolean ,
48234863) : {
48244864 dsMatches : DataStrategyMatch [ ] ;
48254865 revalidatingFetchers : RevalidatingFetcher [ ] ;
@@ -4855,7 +4895,8 @@ function getMatchesToLoad(
48554895 let actionStatus = pendingActionResult
48564896 ? pendingActionResult [ 1 ] . statusCode
48574897 : undefined ;
4858- let shouldSkipRevalidation = actionStatus && actionStatus >= 400 ;
4898+ let shouldSkipRevalidation =
4899+ ( actionStatus && actionStatus >= 400 ) || shouldRevalidate === false ;
48594900
48604901 let baseShouldRevalidateArgs = {
48614902 currentUrl,
0 commit comments