@react-navigation/routers 8.0.0-alpha.6 → 8.0.0-alpha.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -6,7 +6,6 @@ import { createRouteFromAction } from './createRouteFromAction';
6
6
  import type {
7
7
  CommonNavigationAction,
8
8
  DefaultRouterOptions,
9
- NavigationRoute,
10
9
  NavigationState,
11
10
  ParamListBase,
12
11
  Route,
@@ -62,15 +61,10 @@ export type StackNavigationState<ParamList extends ParamListBase> =
62
61
  * Type of the router, in this case, it's stack.
63
62
  */
64
63
  type: 'stack';
65
- /**
66
- * List of routes, which are supposed to be preloaded before navigating to.
67
- */
68
- preloadedRoutes: NavigationRoute<ParamList, keyof ParamList>[];
69
64
  /**
70
65
  * List of route keys to retain in the stack.
71
66
  * When a retained route gets removed from the stack,
72
- * it'll be treated as preloaded route and not completely removed
73
- * So it preserves the route and can be navigated to again.
67
+ * it'll be kept in routes and can be navigated to again.
74
68
  */
75
69
  retainedRouteKeys: string[];
76
70
  };
@@ -141,8 +135,7 @@ export type StackActionHelpers<ParamList extends ParamListBase> = {
141
135
  /**
142
136
  * Enable or disable retaining the current route in the stack.
143
137
  * When a retained route gets removed from the stack,
144
- * it'll be treated as preloaded route and not completely removed
145
- * So it preserves the route and can be navigated to again.
138
+ * it'll be kept in routes and can be navigated to again.
146
139
  *
147
140
  * @param enable Whether to retain the current route in the stack or not.
148
141
  */
@@ -199,7 +192,7 @@ function retainRoutes<ParamList extends ParamListBase>(
199
192
 
200
193
  const retainedRouteKeySet = new Set(nextState.retainedRouteKeys);
201
194
  const nextRouteKeySet = new Set(nextState.routes.map((route) => route.key));
202
- const retainedRoutes = previousState.routes.filter(
195
+ const retainedRoutes = getActiveRoutes(previousState).filter(
203
196
  (route) =>
204
197
  retainedRouteKeySet.has(route.key) && !nextRouteKeySet.has(route.key)
205
198
  );
@@ -212,15 +205,73 @@ function retainRoutes<ParamList extends ParamListBase>(
212
205
  retainedRoutes.map((route) => route.key)
213
206
  );
214
207
 
215
- return {
216
- ...nextState,
217
- preloadedRoutes: retainedRoutes.concat(
218
- nextState.preloadedRoutes.filter(
208
+ return getStateWithRoutes(
209
+ nextState,
210
+ getActiveRoutes(nextState),
211
+ getPreloadedRoutes(nextState),
212
+ retainedRoutes.concat(
213
+ getRetainedRoutes(nextState).filter(
219
214
  (route) => !removedRetainedRouteKeys.has(route.key)
220
215
  )
216
+ )
217
+ );
218
+ }
219
+
220
+ const getActiveRoutes = <ParamList extends ParamListBase>(
221
+ state: StackNavigationState<ParamList>
222
+ ) => state.routes.slice(0, state.index + 1);
223
+
224
+ const getInactiveRoutes = <ParamList extends ParamListBase>(
225
+ state: StackNavigationState<ParamList>
226
+ ) => state.routes.slice(state.index + 1);
227
+
228
+ const getPreloadedRoutes = <ParamList extends ParamListBase>(
229
+ state: StackNavigationState<ParamList>
230
+ ) => {
231
+ const retainedRouteKeySet = new Set(state.retainedRouteKeys);
232
+
233
+ return getInactiveRoutes(state).filter(
234
+ (route) => !retainedRouteKeySet.has(route.key)
235
+ );
236
+ };
237
+
238
+ const getRetainedRoutes = <ParamList extends ParamListBase>(
239
+ state: StackNavigationState<ParamList>
240
+ ) => {
241
+ const retainedRouteKeySet = new Set(state.retainedRouteKeys);
242
+
243
+ return getInactiveRoutes(state).filter((route) =>
244
+ retainedRouteKeySet.has(route.key)
245
+ );
246
+ };
247
+
248
+ const getStateWithRoutes = <ParamList extends ParamListBase>(
249
+ state: StackNavigationState<ParamList>,
250
+ activeRoutes: Route<string>[],
251
+ preloadedRoutes = getPreloadedRoutes(state),
252
+ retainedRoutes = getRetainedRoutes(state)
253
+ ) => {
254
+ const routeKeySet = new Set(activeRoutes.map((route) => route.key));
255
+ const retainedRouteKeySet = new Set(state.retainedRouteKeys);
256
+
257
+ const filteredRetainedRoutes = retainedRoutes.filter(
258
+ (route) => !routeKeySet.has(route.key)
259
+ );
260
+
261
+ const filteredPreloadedRoutes = preloadedRoutes.filter(
262
+ (route) =>
263
+ !retainedRouteKeySet.has(route.key) && !routeKeySet.has(route.key)
264
+ );
265
+
266
+ return {
267
+ ...state,
268
+ index: activeRoutes.length - 1,
269
+ routes: activeRoutes.concat(
270
+ filteredRetainedRoutes,
271
+ filteredPreloadedRoutes
221
272
  ),
222
273
  };
223
- }
274
+ };
224
275
 
225
276
  export function StackRouter(options: StackRouterOptions) {
226
277
  const router: Router<
@@ -244,7 +295,6 @@ export function StackRouter(options: StackRouterOptions) {
244
295
  key: `stack-${nanoid()}`,
245
296
  index: 0,
246
297
  routeNames,
247
- preloadedRoutes: [],
248
298
  retainedRouteKeys: [],
249
299
  routes: [
250
300
  {
@@ -277,29 +327,6 @@ export function StackRouter(options: StackRouterOptions) {
277
327
  : route.params,
278
328
  }));
279
329
 
280
- const preloadedRoutes =
281
- state.preloadedRoutes
282
- ?.filter((route) => routeNames.includes(route.name))
283
- .map(
284
- (route) =>
285
- ({
286
- ...route,
287
- key: route.key || `${route.name}-${nanoid()}`,
288
- params:
289
- routeParamList[route.name] !== undefined
290
- ? {
291
- ...routeParamList[route.name],
292
- ...route.params,
293
- }
294
- : route.params,
295
- }) as Route<string>
296
- ) ?? [];
297
-
298
- const retainedRouteKeys =
299
- state.retainedRouteKeys?.filter((key) =>
300
- [...routes, ...preloadedRoutes].some((route) => route.key === key)
301
- ) ?? [];
302
-
303
330
  if (routes.length === 0) {
304
331
  const initialRouteName =
305
332
  options.initialRouteName !== undefined
@@ -313,14 +340,22 @@ export function StackRouter(options: StackRouterOptions) {
313
340
  });
314
341
  }
315
342
 
343
+ const index = Math.min(
344
+ Math.max(state.index ?? routes.length - 1, 0),
345
+ routes.length - 1
346
+ );
347
+
348
+ const routeKeys = new Set(routes.map((route) => route.key));
349
+ const retainedRouteKeys =
350
+ state.retainedRouteKeys?.filter((key) => routeKeys.has(key)) ?? [];
351
+
316
352
  return {
317
353
  stale: false,
318
354
  type: 'stack',
319
355
  key: `stack-${nanoid()}`,
320
- index: routes.length - 1,
356
+ index,
321
357
  routeNames,
322
358
  routes,
323
- preloadedRoutes,
324
359
  retainedRouteKeys,
325
360
  };
326
361
  },
@@ -329,13 +364,19 @@ export function StackRouter(options: StackRouterOptions) {
329
364
  state,
330
365
  { routeNames, routeParamList, routeKeyChanges }
331
366
  ) {
332
- const routes = state.routes.filter(
367
+ const routes = getActiveRoutes(state).filter(
333
368
  (route) =>
334
369
  routeNames.includes(route.name) &&
335
370
  !routeKeyChanges.includes(route.name)
336
371
  );
337
372
 
338
- const preloadedRoutes = state.preloadedRoutes.filter(
373
+ const preloadedRoutes = getPreloadedRoutes(state).filter(
374
+ (route) =>
375
+ routeNames.includes(route.name) &&
376
+ !routeKeyChanges.includes(route.name)
377
+ );
378
+
379
+ const retainedRoutes = getRetainedRoutes(state).filter(
339
380
  (route) =>
340
381
  routeNames.includes(route.name) &&
341
382
  !routeKeyChanges.includes(route.name)
@@ -356,45 +397,53 @@ export function StackRouter(options: StackRouterOptions) {
356
397
  }
357
398
 
358
399
  const routeKeys = new Set(
359
- [...routes, ...preloadedRoutes].map((route) => route.key)
400
+ [...routes, ...preloadedRoutes, ...retainedRoutes].map(
401
+ (route) => route.key
402
+ )
360
403
  );
361
404
 
362
405
  const retainedRouteKeys = state.retainedRouteKeys.filter((key) =>
363
406
  routeKeys.has(key)
364
407
  );
365
408
 
366
- return {
367
- ...state,
368
- routeNames,
409
+ return getStateWithRoutes(
410
+ {
411
+ ...state,
412
+ routeNames,
413
+ retainedRouteKeys,
414
+ },
369
415
  routes,
370
416
  preloadedRoutes,
371
- retainedRouteKeys,
372
- index: Math.min(state.index, routes.length - 1),
373
- };
417
+ retainedRoutes
418
+ );
374
419
  },
375
420
 
376
421
  getStateForRouteFocus(state, key) {
377
- const index = state.routes.findIndex((r) => r.key === key);
422
+ const routes = getActiveRoutes(state);
423
+ const index = routes.findIndex((r) => r.key === key);
378
424
 
379
425
  if (index === -1 || index === state.index) {
380
426
  return state;
381
427
  }
382
428
 
383
- return retainRoutes(state, {
384
- ...state,
385
- index,
386
- routes: state.routes.slice(0, index + 1),
387
- });
429
+ return retainRoutes(
430
+ state,
431
+ getStateWithRoutes(state, routes.slice(0, index + 1))
432
+ );
388
433
  },
389
434
 
390
435
  getStateForAction(state, action, options) {
391
436
  const { routeParamList } = options;
392
437
 
438
+ const routes = getActiveRoutes(state);
439
+ const preloadedRoutes = getPreloadedRoutes(state);
440
+ const inactiveRoutes = getInactiveRoutes(state);
441
+
393
442
  switch (action.type) {
394
443
  case 'REPLACE': {
395
444
  const currentIndex =
396
445
  action.target === state.key && action.source
397
- ? state.routes.findIndex((r) => r.key === action.source)
446
+ ? routes.findIndex((r) => r.key === action.source)
398
447
  : state.index;
399
448
 
400
449
  if (currentIndex === -1) {
@@ -408,8 +457,8 @@ export function StackRouter(options: StackRouterOptions) {
408
457
  const getId = options.routeGetIdList[action.payload.name];
409
458
  const id = getId?.({ params: action.payload.params });
410
459
 
411
- // Re-use preloaded route if available
412
- let route = state.preloadedRoutes.find(
460
+ // Re-use inactive route if available
461
+ let route = inactiveRoutes.find(
413
462
  (route) =>
414
463
  route.name === action.payload.name &&
415
464
  id === getId?.({ params: route.params })
@@ -417,17 +466,22 @@ export function StackRouter(options: StackRouterOptions) {
417
466
 
418
467
  if (!route) {
419
468
  route = createRouteFromAction({ action, routeParamList });
469
+ } else {
470
+ const params = createParamsFromAction({ action, routeParamList });
471
+
472
+ if (route.params !== params) {
473
+ route = { ...route, params };
474
+ }
420
475
  }
421
476
 
422
- return retainRoutes(state, {
423
- ...state,
424
- routes: state.routes.map((r, i) =>
425
- i === currentIndex ? route : r
426
- ),
427
- preloadedRoutes: state.preloadedRoutes.filter(
428
- (r) => r.key !== route.key
429
- ),
430
- });
477
+ return retainRoutes(
478
+ state,
479
+ getStateWithRoutes(
480
+ state,
481
+ routes.map((r, i) => (i === currentIndex ? route : r)),
482
+ preloadedRoutes.filter((r) => r.key !== route.key)
483
+ )
484
+ );
431
485
  }
432
486
 
433
487
  case 'PUSH':
@@ -442,7 +496,7 @@ export function StackRouter(options: StackRouterOptions) {
442
496
  let route: Route<string> | undefined;
443
497
 
444
498
  if (action.type === 'NAVIGATE') {
445
- const currentRoute = state.routes[state.index];
499
+ const currentRoute = routes[state.index];
446
500
 
447
501
  if (id !== undefined) {
448
502
  if (
@@ -451,8 +505,8 @@ export function StackRouter(options: StackRouterOptions) {
451
505
  ) {
452
506
  route = currentRoute;
453
507
  } else if (action.payload.pop) {
454
- for (let i = state.routes.length - 1; i >= 0; i--) {
455
- const r = state.routes[i];
508
+ for (let i = routes.length - 1; i >= 0; i--) {
509
+ const r = routes[i];
456
510
 
457
511
  if (r.name !== action.payload.name) {
458
512
  continue;
@@ -489,7 +543,7 @@ export function StackRouter(options: StackRouterOptions) {
489
543
  if (action.payload.name === currentRoute.name) {
490
544
  route = currentRoute;
491
545
  } else if (action.payload.pop) {
492
- route = state.routes.findLast(
546
+ route = routes.findLast(
493
547
  (route) => route.name === action.payload.name
494
548
  );
495
549
  }
@@ -497,7 +551,7 @@ export function StackRouter(options: StackRouterOptions) {
497
551
  }
498
552
 
499
553
  if (!route) {
500
- route = state.preloadedRoutes.find(
554
+ route = inactiveRoutes.find(
501
555
  (route) =>
502
556
  route.name === action.payload.name &&
503
557
  id === getId?.({ params: route.params })
@@ -520,16 +574,16 @@ export function StackRouter(options: StackRouterOptions) {
520
574
  params = createParamsFromAction({ action, routeParamList });
521
575
  }
522
576
 
523
- let routes: Route<string>[];
577
+ let nextRoutes: Route<string>[];
524
578
 
525
579
  if (route) {
526
580
  if (action.type === 'NAVIGATE' && action.payload.pop) {
527
- routes = [];
581
+ nextRoutes = [];
528
582
 
529
583
  // Get all routes until the matching one
530
- for (const r of state.routes) {
584
+ for (const r of routes) {
531
585
  if (r.key === route.key) {
532
- routes.push({
586
+ nextRoutes.push({
533
587
  ...route,
534
588
  path:
535
589
  action.payload.path !== undefined
@@ -540,11 +594,22 @@ export function StackRouter(options: StackRouterOptions) {
540
594
  break;
541
595
  }
542
596
 
543
- routes.push(r);
597
+ nextRoutes.push(r);
598
+ }
599
+
600
+ if (!nextRoutes.some((r) => r.key === route.key)) {
601
+ nextRoutes.push({
602
+ ...route,
603
+ path:
604
+ action.payload.path !== undefined
605
+ ? action.payload.path
606
+ : route.path,
607
+ params,
608
+ });
544
609
  }
545
610
  } else {
546
- routes = state.routes.filter((r) => r.key !== route.key);
547
- routes.push({
611
+ nextRoutes = routes.filter((r) => r.key !== route.key);
612
+ nextRoutes.push({
548
613
  ...route,
549
614
  path:
550
615
  action.type === 'NAVIGATE' &&
@@ -555,8 +620,8 @@ export function StackRouter(options: StackRouterOptions) {
555
620
  });
556
621
  }
557
622
  } else {
558
- routes = [
559
- ...state.routes,
623
+ nextRoutes = [
624
+ ...routes,
560
625
  {
561
626
  key: `${action.payload.name}-${nanoid()}`,
562
627
  name: action.payload.name,
@@ -567,23 +632,29 @@ export function StackRouter(options: StackRouterOptions) {
567
632
  ];
568
633
  }
569
634
 
570
- return retainRoutes(state, {
571
- ...state,
572
- index: routes.length - 1,
573
- preloadedRoutes: state.preloadedRoutes.filter(
574
- (route) => routes[routes.length - 1].key !== route.key
575
- ),
576
- routes,
577
- });
635
+ return retainRoutes(
636
+ state,
637
+ getStateWithRoutes(
638
+ state,
639
+ nextRoutes,
640
+ preloadedRoutes.filter(
641
+ (route) => nextRoutes[nextRoutes.length - 1].key !== route.key
642
+ )
643
+ )
644
+ );
578
645
  }
579
646
 
580
647
  case 'POP': {
581
648
  let currentIndex =
582
649
  action.target === state.key && action.source
583
- ? state.routes.findIndex((r) => r.key === action.source)
650
+ ? routes.findIndex((r) => r.key === action.source)
584
651
  : state.index;
585
652
 
586
- let route = state.routes[currentIndex];
653
+ if (currentIndex === -1) {
654
+ return null;
655
+ }
656
+
657
+ let route = routes[currentIndex];
587
658
 
588
659
  /**
589
660
  * When popping entries,
@@ -596,11 +667,11 @@ export function StackRouter(options: StackRouterOptions) {
596
667
  */
597
668
  if (route.history?.length || currentIndex > 0) {
598
669
  let count = action.payload.count;
599
- let routes = state.routes;
670
+ let nextRoutes = routes;
600
671
 
601
672
  while (count > 0 && (route.history?.length || currentIndex > 0)) {
602
673
  if (route.history?.length) {
603
- routes = [...routes];
674
+ nextRoutes = [...nextRoutes];
604
675
 
605
676
  const end = Math.min(count, route.history.length);
606
677
  const last = route.history.at(-end);
@@ -609,7 +680,7 @@ export function StackRouter(options: StackRouterOptions) {
609
680
 
610
681
  count = count - removed;
611
682
 
612
- routes[currentIndex] = {
683
+ nextRoutes[currentIndex] = {
613
684
  ...route,
614
685
  params: last?.type === 'params' ? last.params : route.params,
615
686
  history,
@@ -617,33 +688,29 @@ export function StackRouter(options: StackRouterOptions) {
617
688
  }
618
689
 
619
690
  if (currentIndex > 0 && count > 0) {
620
- const length = routes.length;
691
+ const length = nextRoutes.length;
621
692
  const end = Math.max(currentIndex - count + 1, 1);
622
693
 
623
- routes = routes
694
+ nextRoutes = nextRoutes
624
695
  .slice(0, end)
625
- .concat(routes.slice(currentIndex + 1));
696
+ .concat(nextRoutes.slice(currentIndex + 1));
626
697
 
627
- const removed = length - routes.length;
698
+ const removed = length - nextRoutes.length;
628
699
 
629
700
  count = count - removed;
630
- currentIndex = routes.length - 1;
631
- route = routes[currentIndex];
701
+ currentIndex = nextRoutes.length - 1;
702
+ route = nextRoutes[currentIndex];
632
703
  }
633
704
  }
634
705
 
635
- return retainRoutes(state, {
636
- ...state,
637
- index: routes.length - 1,
638
- routes,
639
- });
706
+ return retainRoutes(state, getStateWithRoutes(state, nextRoutes));
640
707
  }
641
708
 
642
709
  return null;
643
710
  }
644
711
 
645
712
  case 'POP_TO_TOP': {
646
- let route = state.routes[0];
713
+ let route = routes[0];
647
714
 
648
715
  if (state.index > 0 || route.history?.length) {
649
716
  if (route.history?.length) {
@@ -653,11 +720,7 @@ export function StackRouter(options: StackRouterOptions) {
653
720
  };
654
721
  }
655
722
 
656
- return retainRoutes(state, {
657
- ...state,
658
- index: 0,
659
- routes: [route],
660
- });
723
+ return retainRoutes(state, getStateWithRoutes(state, [route]));
661
724
  }
662
725
 
663
726
  return null;
@@ -666,7 +729,7 @@ export function StackRouter(options: StackRouterOptions) {
666
729
  case 'POP_TO': {
667
730
  const currentIndex =
668
731
  action.target === state.key && action.source
669
- ? state.routes.findLastIndex((r) => r.key === action.source)
732
+ ? routes.findLastIndex((r) => r.key === action.source)
670
733
  : state.index;
671
734
 
672
735
  if (currentIndex === -1) {
@@ -686,7 +749,7 @@ export function StackRouter(options: StackRouterOptions) {
686
749
 
687
750
  if (id !== undefined) {
688
751
  for (let i = currentIndex; i >= 0; i--) {
689
- const r = state.routes[i];
752
+ const r = routes[i];
690
753
 
691
754
  if (r.name !== action.payload.name) {
692
755
  continue;
@@ -714,11 +777,11 @@ export function StackRouter(options: StackRouterOptions) {
714
777
  }
715
778
  }
716
779
  }
717
- } else if (state.routes[currentIndex].name === action.payload.name) {
780
+ } else if (routes[currentIndex].name === action.payload.name) {
718
781
  index = currentIndex;
719
782
  } else {
720
783
  for (let i = currentIndex; i >= 0; i--) {
721
- if (state.routes[i].name === action.payload.name) {
784
+ if (routes[i].name === action.payload.name) {
722
785
  index = i;
723
786
  break;
724
787
  }
@@ -727,8 +790,8 @@ export function StackRouter(options: StackRouterOptions) {
727
790
 
728
791
  // If the route doesn't exist, remove the current route and add the new one
729
792
  if (index === -1) {
730
- // Re-use preloaded route if available
731
- let route = state.preloadedRoutes.find(
793
+ // Re-use inactive route if available
794
+ let route = inactiveRoutes.find(
732
795
  (route) =>
733
796
  route.name === action.payload.name &&
734
797
  id === getId?.({ params: route.params })
@@ -736,21 +799,27 @@ export function StackRouter(options: StackRouterOptions) {
736
799
 
737
800
  if (!route) {
738
801
  route = createRouteFromAction({ action, routeParamList });
802
+ } else {
803
+ const params = createParamsFromAction({ action, routeParamList });
804
+
805
+ if (route.params !== params) {
806
+ route = { ...route, params };
807
+ }
739
808
  }
740
809
 
741
- const routes = state.routes.slice(0, currentIndex).concat(route);
810
+ const nextRoutes = routes.slice(0, currentIndex).concat(route);
742
811
 
743
- return retainRoutes(state, {
744
- ...state,
745
- index: routes.length - 1,
746
- routes,
747
- preloadedRoutes: state.preloadedRoutes.filter(
748
- (r) => r.key !== route.key
749
- ),
750
- });
812
+ return retainRoutes(
813
+ state,
814
+ getStateWithRoutes(
815
+ state,
816
+ nextRoutes,
817
+ preloadedRoutes.filter((r) => r.key !== route.key)
818
+ )
819
+ );
751
820
  }
752
821
 
753
- const route = state.routes[index];
822
+ const route = routes[index];
754
823
 
755
824
  let baseParams = route.params;
756
825
  let history = route.history;
@@ -776,20 +845,19 @@ export function StackRouter(options: StackRouterOptions) {
776
845
  params = createParamsFromAction({ action, routeParamList });
777
846
  }
778
847
 
779
- return retainRoutes(state, {
780
- ...state,
781
- index,
782
- routes: [
783
- ...state.routes.slice(0, index),
848
+ return retainRoutes(
849
+ state,
850
+ getStateWithRoutes(state, [
851
+ ...routes.slice(0, index),
784
852
  params !== baseParams || historyIndex !== undefined
785
853
  ? { ...route, params, history }
786
- : state.routes[index],
787
- ],
788
- });
854
+ : routes[index],
855
+ ])
856
+ );
789
857
  }
790
858
 
791
859
  case 'GO_BACK':
792
- if (state.index > 0 || state.routes[state.index].history?.length) {
860
+ if (state.index > 0 || routes[state.index].history?.length) {
793
861
  return router.getStateForAction(
794
862
  state,
795
863
  {
@@ -805,12 +873,9 @@ export function StackRouter(options: StackRouterOptions) {
805
873
  return null;
806
874
 
807
875
  case 'RETAIN': {
808
- const routeKey = action.source ?? state.routes[state.index].key;
876
+ const routeKey = action.source ?? routes[state.index].key;
809
877
 
810
- if (
811
- !state.routes.some((route) => route.key === routeKey) &&
812
- !state.preloadedRoutes.some((route) => route.key === routeKey)
813
- ) {
878
+ if (!state.routes.some((route) => route.key === routeKey)) {
814
879
  return null;
815
880
  }
816
881
 
@@ -829,18 +894,23 @@ export function StackRouter(options: StackRouterOptions) {
829
894
  return state;
830
895
  }
831
896
 
832
- return {
833
- ...state,
834
- preloadedRoutes: state.preloadedRoutes.filter(
835
- (route) => route.key !== routeKey
836
- ),
837
- retainedRouteKeys: state.retainedRouteKeys.filter(
838
- (key) => key !== routeKey
839
- ),
840
- };
897
+ return getStateWithRoutes(
898
+ {
899
+ ...state,
900
+ retainedRouteKeys: state.retainedRouteKeys.filter(
901
+ (key) => key !== routeKey
902
+ ),
903
+ },
904
+ routes,
905
+ preloadedRoutes.filter((route) => route.key !== routeKey)
906
+ );
841
907
  }
842
908
 
843
909
  case 'PRELOAD': {
910
+ if (!state.routeNames.includes(action.payload.name)) {
911
+ return null;
912
+ }
913
+
844
914
  const getId = options.routeGetIdList[action.payload.name];
845
915
  const id = getId?.({ params: action.payload.params });
846
916
  const params = createParamsFromAction({ action, routeParamList });
@@ -848,56 +918,59 @@ export function StackRouter(options: StackRouterOptions) {
848
918
  let route: Route<string> | undefined;
849
919
 
850
920
  if (action.payload.reuse) {
851
- route = state.preloadedRoutes.findLast(
921
+ route = preloadedRoutes.findLast(
852
922
  (route) =>
853
923
  route.name === action.payload.name &&
854
924
  (id === undefined || id === getId?.({ params: route.params }))
855
925
  );
856
926
 
857
927
  if (route) {
858
- return {
859
- ...state,
860
- preloadedRoutes: state.preloadedRoutes.map((r) =>
928
+ return getStateWithRoutes(
929
+ state,
930
+ routes,
931
+ preloadedRoutes.map((r) =>
861
932
  r.key === route?.key && r.params !== params
862
933
  ? { ...r, params }
863
934
  : r
864
- ),
865
- };
935
+ )
936
+ );
866
937
  }
867
938
  }
868
939
 
869
940
  if (id !== undefined) {
870
- route = state.routes.findLast(
941
+ route = routes.findLast(
871
942
  (route) =>
872
943
  route.name === action.payload.name &&
873
944
  id === getId?.({ params: route.params })
874
945
  );
875
946
  } else if (action.payload.reuse) {
876
- route = state.routes.findLast(
947
+ route = routes.findLast(
877
948
  (route) => route.name === action.payload.name
878
949
  );
879
950
  }
880
951
 
881
952
  if (route) {
882
- return {
883
- ...state,
884
- routes: state.routes.map((r) =>
953
+ return getStateWithRoutes(
954
+ state,
955
+ routes.map((r) =>
885
956
  r.key === route.key && r.params !== params
886
957
  ? { ...r, params }
887
958
  : r
888
959
  ),
889
- };
960
+ preloadedRoutes
961
+ );
890
962
  } else {
891
- return {
892
- ...state,
893
- preloadedRoutes: state.preloadedRoutes
963
+ return getStateWithRoutes(
964
+ state,
965
+ routes,
966
+ preloadedRoutes
894
967
  .filter(
895
968
  (r) =>
896
969
  r.name !== action.payload.name ||
897
970
  id !== getId?.({ params: r.params })
898
971
  )
899
- .concat(createRouteFromAction({ action, routeParamList })),
900
- };
972
+ .concat(createRouteFromAction({ action, routeParamList }))
973
+ );
901
974
  }
902
975
  }
903
976
 
@@ -906,10 +979,6 @@ export function StackRouter(options: StackRouterOptions) {
906
979
  }
907
980
  },
908
981
 
909
- getRoutesFromState(state) {
910
- return [...state.routes, ...state.preloadedRoutes];
911
- },
912
-
913
982
  actionCreators: StackActions,
914
983
  };
915
984