@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/build/cjs/RouterProvider.js +49 -47
- package/build/cjs/RouterProvider.js.map +1 -1
- package/build/cjs/react.js +2 -1
- package/build/cjs/react.js.map +1 -1
- package/build/cjs/router.js.map +1 -1
- package/build/esm/index.js +51 -48
- package/build/esm/index.js.map +1 -1
- package/build/stats-html.html +1 -1
- package/build/stats-react.json +167 -167
- package/build/types/router.d.ts +3 -0
- package/build/umd/index.development.js +51 -48
- package/build/umd/index.development.js.map +1 -1
- package/build/umd/index.production.js +1 -1
- package/build/umd/index.production.js.map +1 -1
- package/package.json +2 -2
- package/src/RouterProvider.tsx +58 -61
- package/src/react.tsx +2 -1
- package/src/router.ts +2 -0
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.
|
|
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.
|
|
45
|
+
"@tanstack/history": "0.0.1-beta.207"
|
|
46
46
|
},
|
|
47
47
|
"scripts": {
|
|
48
48
|
"build": "rollup --config rollup.config.js"
|
package/src/RouterProvider.tsx
CHANGED
|
@@ -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 (
|
|
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:
|
|
1009
|
+
to: next ?? state.location,
|
|
1005
1010
|
pathChanged: pathDidChange,
|
|
1006
1011
|
})
|
|
1007
1012
|
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
}))
|
|
1014
|
-
}
|
|
1013
|
+
// Ingest the new location
|
|
1014
|
+
setState((s) => ({
|
|
1015
|
+
...s,
|
|
1016
|
+
location: next,
|
|
1017
|
+
}))
|
|
1015
1018
|
|
|
1016
1019
|
// Match the routes
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
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:
|
|
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
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
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
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
if (state.resolvedLocation !== state.location) {
|
|
1294
|
-
safeLoad()
|
|
1288
|
+
try {
|
|
1289
|
+
load()
|
|
1290
|
+
} catch (err) {
|
|
1291
|
+
console.error(err)
|
|
1295
1292
|
}
|
|
1296
|
-
}
|
|
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
|
|
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
|
|