@tanstack/react-router 0.0.1-beta.206 → 0.0.1-beta.207

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.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tanstack/react-router",
3
3
  "author": "Tanner Linsley",
4
- "version": "0.0.1-beta.206",
4
+ "version": "0.0.1-beta.207",
5
5
  "license": "MIT",
6
6
  "repository": "tanstack/router",
7
7
  "homepage": "https://tanstack.com/router",
@@ -42,7 +42,7 @@
42
42
  "@babel/runtime": "^7.16.7",
43
43
  "tiny-invariant": "^1.3.1",
44
44
  "tiny-warning": "^1.0.3",
45
- "@tanstack/history": "0.0.1-beta.206"
45
+ "@tanstack/history": "0.0.1-beta.207"
46
46
  },
47
47
  "scripts": {
48
48
  "build": "rollup --config rollup.config.js"
@@ -134,6 +134,10 @@ export type RouterContext<
134
134
 
135
135
  export const routerContext = React.createContext<RouterContext<any>>(null!)
136
136
 
137
+ if (typeof document !== 'undefined') {
138
+ window.__TSR_ROUTER_CONTEXT__ = routerContext as any
139
+ }
140
+
137
141
  export function getInitialRouterState(
138
142
  location: ParsedLocation,
139
143
  ): RouterState<any> {
@@ -175,6 +179,14 @@ export function RouterProvider<
175
179
 
176
180
  const navigateTimeoutRef = React.useRef<NodeJS.Timeout | null>(null)
177
181
 
182
+ const latestLoadPromiseRef = React.useRef<Promise<void>>(Promise.resolve())
183
+
184
+ const checkLatest = (promise: Promise<void>): undefined | Promise<void> => {
185
+ return latestLoadPromiseRef.current !== promise
186
+ ? latestLoadPromiseRef.current
187
+ : undefined
188
+ }
189
+
178
190
  const parseLocation = useStableCallback(
179
191
  (
180
192
  previousLocation?: ParsedLocation,
@@ -346,8 +358,6 @@ export function RouterProvider<
346
358
  [routesByPath],
347
359
  )
348
360
 
349
- const latestLoadPromiseRef = React.useRef<Promise<void>>(Promise.resolve())
350
-
351
361
  const matchRoutes = useStableCallback(
352
362
  <TRouteTree extends AnyRoute>(
353
363
  pathname: string,
@@ -786,12 +796,15 @@ export function RouterProvider<
786
796
 
787
797
  const loadMatches = useStableCallback(
788
798
  async ({
799
+ checkLatest,
789
800
  matches,
790
801
  preload,
791
802
  }: {
803
+ checkLatest: () => Promise<void> | undefined
792
804
  matches: AnyRouteMatch[]
793
805
  preload?: boolean
794
- }) => {
806
+ }): Promise<RouteMatch[]> => {
807
+ let latestPromise
795
808
  let firstBadMatchIndex: number | undefined
796
809
 
797
810
  // Check each match middleware to see if the route can be accessed
@@ -864,7 +877,7 @@ export function RouterProvider<
864
877
  } catch (err) {
865
878
  if (isRedirect(err)) {
866
879
  if (!preload) navigate(err as any)
867
- return
880
+ return matches
868
881
  }
869
882
 
870
883
  throw err
@@ -883,14 +896,6 @@ export function RouterProvider<
883
896
  return getRouteMatch(state, match.id)?.loadPromise
884
897
  }
885
898
 
886
- const fetchedAt = Date.now()
887
- const checkLatest = () => {
888
- const latest = getRouteMatch(state, match.id)
889
- return latest && latest.fetchedAt !== fetchedAt
890
- ? latest.loadPromise
891
- : undefined
892
- }
893
-
894
899
  const handleIfRedirect = (err: any) => {
895
900
  if (isRedirect(err)) {
896
901
  if (!preload) {
@@ -902,8 +907,6 @@ export function RouterProvider<
902
907
  }
903
908
 
904
909
  const load = async () => {
905
- let latestPromise
906
-
907
910
  try {
908
911
  const componentsPromise = Promise.all(
909
912
  componentTypes.map(async (type) => {
@@ -953,6 +956,15 @@ export function RouterProvider<
953
956
  updatedAt: Date.now(),
954
957
  }
955
958
  }
959
+
960
+ if (!preload) {
961
+ setState((s) => ({
962
+ ...s,
963
+ matches: s.matches.map((d) =>
964
+ d.id === match.id ? match : d,
965
+ ),
966
+ }))
967
+ }
956
968
  }
957
969
 
958
970
  let loadPromise: Promise<void> | undefined
@@ -960,7 +972,7 @@ export function RouterProvider<
960
972
  matches[index] = match = {
961
973
  ...match,
962
974
  isFetching: true,
963
- fetchedAt,
975
+ fetchedAt: Date.now(),
964
976
  invalid: false,
965
977
  }
966
978
 
@@ -977,48 +989,38 @@ export function RouterProvider<
977
989
  })
978
990
 
979
991
  await Promise.all(matchPromises)
992
+ return matches
980
993
  },
981
994
  )
982
995
 
983
- const load = useStableCallback<LoadFn>(async (opts) => {
996
+ const load = useStableCallback<LoadFn>(async () => {
984
997
  const promise = new Promise<void>(async (resolve, reject) => {
998
+ const next = latestLocationRef.current
985
999
  const prevLocation = state.resolvedLocation
986
- const pathDidChange = !!(
987
- opts?.next && prevLocation!.href !== opts.next.href
988
- )
989
-
1000
+ const pathDidChange = !!(next && prevLocation!.href !== next.href)
990
1001
  let latestPromise: Promise<void> | undefined | null
991
1002
 
992
- const checkLatest = (): undefined | Promise<void> | null => {
993
- return latestLoadPromiseRef.current !== promise
994
- ? latestLoadPromiseRef.current
995
- : undefined
996
- }
997
-
998
1003
  // Cancel any pending matches
999
1004
  cancelMatches(state)
1000
1005
 
1001
1006
  router.emit({
1002
1007
  type: 'onBeforeLoad',
1003
1008
  from: prevLocation,
1004
- to: opts?.next ?? state.location,
1009
+ to: next ?? state.location,
1005
1010
  pathChanged: pathDidChange,
1006
1011
  })
1007
1012
 
1008
- if (opts?.next) {
1009
- // Ingest the new location
1010
- setState((s) => ({
1011
- ...s,
1012
- location: opts.next! as any,
1013
- }))
1014
- }
1013
+ // Ingest the new location
1014
+ setState((s) => ({
1015
+ ...s,
1016
+ location: next,
1017
+ }))
1015
1018
 
1016
1019
  // Match the routes
1017
- const matches: RouteMatch<any, any>[] = matchRoutes(
1018
- state.location.pathname,
1019
- state.location.search,
1020
+ let matches: RouteMatch<any, any>[] = matchRoutes(
1021
+ next.pathname,
1022
+ next.search,
1020
1023
  {
1021
- throwOnError: opts?.throwOnError,
1022
1024
  debug: true,
1023
1025
  },
1024
1026
  )
@@ -1030,10 +1032,11 @@ export function RouterProvider<
1030
1032
  }))
1031
1033
 
1032
1034
  try {
1033
- // Load the matches
1034
1035
  try {
1036
+ // Load the matches
1035
1037
  await loadMatches({
1036
1038
  matches,
1039
+ checkLatest: () => checkLatest(promise),
1037
1040
  })
1038
1041
  } catch (err) {
1039
1042
  // swallow this error, since we'll display the
@@ -1041,7 +1044,7 @@ export function RouterProvider<
1041
1044
  }
1042
1045
 
1043
1046
  // Only apply the latest transition
1044
- if ((latestPromise = checkLatest())) {
1047
+ if ((latestPromise = checkLatest(promise))) {
1045
1048
  return latestPromise
1046
1049
  }
1047
1050
 
@@ -1078,14 +1081,14 @@ export function RouterProvider<
1078
1081
  router.emit({
1079
1082
  type: 'onLoad',
1080
1083
  from: prevLocation,
1081
- to: state.location,
1084
+ to: next,
1082
1085
  pathChanged: pathDidChange,
1083
1086
  })
1084
1087
 
1085
1088
  resolve()
1086
1089
  } catch (err) {
1087
1090
  // Only apply the latest transition
1088
- if ((latestPromise = checkLatest())) {
1091
+ if ((latestPromise = checkLatest(promise))) {
1089
1092
  return latestPromise
1090
1093
  }
1091
1094
 
@@ -1098,14 +1101,6 @@ export function RouterProvider<
1098
1101
  return latestLoadPromiseRef.current
1099
1102
  })
1100
1103
 
1101
- const safeLoad = React.useCallback(async () => {
1102
- try {
1103
- return load()
1104
- } catch (err) {
1105
- // Don't do anything
1106
- }
1107
- }, [])
1108
-
1109
1104
  const preloadRoute = useStableCallback(
1110
1105
  async (navigateOpts: BuildNextOptions = state.location) => {
1111
1106
  let next = buildLocation(navigateOpts)
@@ -1117,6 +1112,7 @@ export function RouterProvider<
1117
1112
  await loadMatches({
1118
1113
  matches,
1119
1114
  preload: true,
1115
+ checkLatest: () => undefined,
1120
1116
  })
1121
1117
 
1122
1118
  return [last(matches)!, matches] as const
@@ -1259,10 +1255,13 @@ export function RouterProvider<
1259
1255
  latestLocationRef.current = parseLocation(latestLocationRef.current)
1260
1256
 
1261
1257
  React.startTransition(() => {
1262
- setState((s) => ({
1263
- ...s,
1264
- location: latestLocationRef.current,
1265
- }))
1258
+ if (state.location !== latestLocationRef.current) {
1259
+ try {
1260
+ load()
1261
+ } catch (err) {
1262
+ console.error(err)
1263
+ }
1264
+ }
1266
1265
  })
1267
1266
  })
1268
1267
 
@@ -1286,14 +1285,12 @@ export function RouterProvider<
1286
1285
 
1287
1286
  if (initialLoad.current) {
1288
1287
  initialLoad.current = false
1289
- safeLoad()
1290
- }
1291
-
1292
- React.useLayoutEffect(() => {
1293
- if (state.resolvedLocation !== state.location) {
1294
- safeLoad()
1288
+ try {
1289
+ load()
1290
+ } catch (err) {
1291
+ console.error(err)
1295
1292
  }
1296
- }, [state.location])
1293
+ }
1297
1294
 
1298
1295
  const isFetching = React.useMemo(
1299
1296
  () => [...state.matches, ...state.pendingMatches].some((d) => d.isFetching),
package/src/react.tsx CHANGED
@@ -404,7 +404,8 @@ export type RouterProps<
404
404
  export function useRouter<
405
405
  TRouteTree extends AnyRoute = RegisteredRouter['routeTree'],
406
406
  >(): RouterContext<TRouteTree> {
407
- const value = React.useContext(routerContext)
407
+ const resolvedContext = window.__TSR_ROUTER_CONTEXT__ || routerContext
408
+ const value = React.useContext(resolvedContext)
408
409
  warning(value, 'useRouter must be used inside a <RouterProvider> component!')
409
410
  return value as any
410
411
  }
package/src/router.ts CHANGED
@@ -21,12 +21,14 @@ import { RouteMatch } from './RouteMatch'
21
21
  import { ParsedLocation } from './location'
22
22
  import { LocationState } from './location'
23
23
  import { SearchSerializer, SearchParser } from './searchParams'
24
+ import { RouterContext } from './RouterProvider'
24
25
 
25
26
  //
26
27
 
27
28
  declare global {
28
29
  interface Window {
29
30
  __TSR_DEHYDRATED__?: HydrationCtx
31
+ __TSR_ROUTER_CONTEXT__?: React.Context<RouterContext<any>>
30
32
  }
31
33
  }
32
34