@tanstack/react-router 0.0.1-beta.234 → 0.0.1-beta.236
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/Matches.js +9 -8
- package/build/cjs/Matches.js.map +1 -1
- package/build/cjs/RouterProvider.js +28 -31
- package/build/cjs/RouterProvider.js.map +1 -1
- package/build/cjs/router.js +49 -37
- package/build/cjs/router.js.map +1 -1
- package/build/esm/index.js +86 -76
- package/build/esm/index.js.map +1 -1
- package/build/stats-html.html +1 -1
- package/build/stats-react.json +566 -285
- package/build/types/router.d.ts +6 -3
- package/build/umd/index.development.js +354 -80
- package/build/umd/index.development.js.map +1 -1
- package/build/umd/index.production.js +2 -2
- package/build/umd/index.production.js.map +1 -1
- package/package.json +4 -2
- package/src/Matches.tsx +23 -10
- package/src/RouterProvider.tsx +35 -34
- package/src/router.ts +62 -44
package/build/esm/index.js
CHANGED
|
@@ -15,6 +15,8 @@ export { default as invariant } from 'tiny-invariant';
|
|
|
15
15
|
import warning from 'tiny-warning';
|
|
16
16
|
export { default as warning } from 'tiny-warning';
|
|
17
17
|
import * as React from 'react';
|
|
18
|
+
import { useStore } from '@tanstack/react-store';
|
|
19
|
+
import { Store } from '@tanstack/store';
|
|
18
20
|
|
|
19
21
|
function CatchBoundary(props) {
|
|
20
22
|
const errorComponent = props.errorComponent ?? ErrorComponent;
|
|
@@ -608,12 +610,10 @@ function createRouteMask(opts) {
|
|
|
608
610
|
|
|
609
611
|
function Matches() {
|
|
610
612
|
const {
|
|
611
|
-
routesById
|
|
612
|
-
state
|
|
613
|
+
routesById
|
|
613
614
|
} = useRouter();
|
|
614
|
-
const
|
|
615
|
-
|
|
616
|
-
} = state;
|
|
615
|
+
const routerState = useRouterState();
|
|
616
|
+
const matches = routerState.pendingMatches?.some(d => d.showPending) ? routerState.pendingMatches : routerState.matches;
|
|
617
617
|
const locationKey = useRouterState().location.state.key;
|
|
618
618
|
const route = routesById[rootRouteId];
|
|
619
619
|
const errorComponent = React.useCallback(props => {
|
|
@@ -759,7 +759,8 @@ function useMatch(opts) {
|
|
|
759
759
|
const nearestMatchRouteId = nearestMatch?.routeId;
|
|
760
760
|
const matchRouteId = useRouterState({
|
|
761
761
|
select: state => {
|
|
762
|
-
const
|
|
762
|
+
const matches = state.pendingMatches?.some(d => d.showPending) ? state.pendingMatches : state.matches;
|
|
763
|
+
const match = opts?.from ? matches.find(d => d.routeId === opts?.from) : matches.find(d => d.id === nearestMatch.id);
|
|
763
764
|
return match.routeId;
|
|
764
765
|
}
|
|
765
766
|
});
|
|
@@ -768,7 +769,8 @@ function useMatch(opts) {
|
|
|
768
769
|
}
|
|
769
770
|
const matchSelection = useRouterState({
|
|
770
771
|
select: state => {
|
|
771
|
-
const
|
|
772
|
+
const matches = state.pendingMatches?.some(d => d.showPending) ? state.pendingMatches : state.matches;
|
|
773
|
+
const match = opts?.from ? matches.find(d => d.routeId === opts?.from) : matches.find(d => d.id === nearestMatch.id);
|
|
772
774
|
invariant(match, `Could not find ${opts?.from ? `an active match from "${opts.from}"` : 'a nearest match!'}`);
|
|
773
775
|
return opts?.select ? opts.select(match) : match;
|
|
774
776
|
}
|
|
@@ -780,7 +782,8 @@ function useMatches(opts) {
|
|
|
780
782
|
const contextMatches = React.useContext(matchesContext);
|
|
781
783
|
return useRouterState({
|
|
782
784
|
select: state => {
|
|
783
|
-
|
|
785
|
+
let matches = state.pendingMatches?.some(d => d.showPending) ? state.pendingMatches : state.matches;
|
|
786
|
+
matches = matches.slice(matches.findIndex(d => d.id === contextMatches[0]?.id));
|
|
784
787
|
return opts?.select ? opts.select(matches) : matches;
|
|
785
788
|
}
|
|
786
789
|
});
|
|
@@ -821,31 +824,29 @@ function RouterProvider({
|
|
|
821
824
|
function RouterProviderInner({
|
|
822
825
|
router
|
|
823
826
|
}) {
|
|
824
|
-
const [preState, setState] = React.useState(() => router.state);
|
|
825
827
|
const [isTransitioning, startReactTransition] = React.useTransition();
|
|
826
|
-
const isAnyTransitioning = isTransitioning || preState.matches.some(d => d.status === 'pending');
|
|
827
|
-
const state = React.useMemo(() => ({
|
|
828
|
-
...preState,
|
|
829
|
-
status: isAnyTransitioning ? 'pending' : 'idle',
|
|
830
|
-
location: isTransitioning ? router.latestLocation : preState.location,
|
|
831
|
-
pendingMatches: router.pendingMatches
|
|
832
|
-
}), [preState, isTransitioning]);
|
|
833
|
-
router.setState = setState;
|
|
834
|
-
router.state = state;
|
|
835
828
|
router.startReactTransition = startReactTransition;
|
|
829
|
+
React.useEffect(() => {
|
|
830
|
+
if (isTransitioning) {
|
|
831
|
+
router.__store.setState(s => ({
|
|
832
|
+
...s,
|
|
833
|
+
isTransitioning
|
|
834
|
+
}));
|
|
835
|
+
}
|
|
836
|
+
}, [isTransitioning]);
|
|
836
837
|
const tryLoad = () => {
|
|
837
|
-
startReactTransition(() => {
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
})
|
|
838
|
+
// startReactTransition(() => {
|
|
839
|
+
try {
|
|
840
|
+
router.load();
|
|
841
|
+
} catch (err) {
|
|
842
|
+
console.error(err);
|
|
843
|
+
}
|
|
844
|
+
// })
|
|
844
845
|
};
|
|
845
846
|
useLayoutEffect$1(() => {
|
|
846
847
|
const unsub = router.history.subscribe(() => {
|
|
847
848
|
router.latestLocation = router.parseLocation(router.latestLocation);
|
|
848
|
-
if (state.location !== router.latestLocation) {
|
|
849
|
+
if (router.state.location !== router.latestLocation) {
|
|
849
850
|
tryLoad();
|
|
850
851
|
}
|
|
851
852
|
});
|
|
@@ -855,7 +856,7 @@ function RouterProviderInner({
|
|
|
855
856
|
hash: true,
|
|
856
857
|
state: true
|
|
857
858
|
});
|
|
858
|
-
if (state.location.href !== nextLocation.href) {
|
|
859
|
+
if (router.state.location.href !== nextLocation.href) {
|
|
859
860
|
router.commitLocation({
|
|
860
861
|
...nextLocation,
|
|
861
862
|
replace: true
|
|
@@ -866,20 +867,21 @@ function RouterProviderInner({
|
|
|
866
867
|
};
|
|
867
868
|
}, [router.history]);
|
|
868
869
|
useLayoutEffect$1(() => {
|
|
869
|
-
if (!isTransitioning && state.resolvedLocation !== state.location) {
|
|
870
|
+
if (!isTransitioning && router.state.resolvedLocation !== router.state.location) {
|
|
870
871
|
router.emit({
|
|
871
872
|
type: 'onResolved',
|
|
872
|
-
fromLocation: state.resolvedLocation,
|
|
873
|
-
toLocation: state.location,
|
|
874
|
-
pathChanged: state.location.href !== state.resolvedLocation?.href
|
|
873
|
+
fromLocation: router.state.resolvedLocation,
|
|
874
|
+
toLocation: router.state.location,
|
|
875
|
+
pathChanged: router.state.location.href !== router.state.resolvedLocation?.href
|
|
875
876
|
});
|
|
876
877
|
router.pendingMatches = [];
|
|
877
|
-
setState(s => ({
|
|
878
|
+
router.__store.setState(s => ({
|
|
878
879
|
...s,
|
|
880
|
+
isTransitioning: false,
|
|
879
881
|
resolvedLocation: s.location
|
|
880
882
|
}));
|
|
881
883
|
}
|
|
882
|
-
});
|
|
884
|
+
}, [isTransitioning]);
|
|
883
885
|
useLayoutEffect$1(() => {
|
|
884
886
|
if (!window.__TSR_DEHYDRATED__) {
|
|
885
887
|
tryLoad();
|
|
@@ -890,14 +892,11 @@ function RouterProviderInner({
|
|
|
890
892
|
}, /*#__PURE__*/React.createElement(Matches, null));
|
|
891
893
|
}
|
|
892
894
|
function getRouteMatch(state, id) {
|
|
893
|
-
return [...state.pendingMatches, ...state.matches].find(d => d.id === id);
|
|
895
|
+
return [...(state.pendingMatches ?? []), ...state.matches].find(d => d.id === id);
|
|
894
896
|
}
|
|
895
897
|
function useRouterState(opts) {
|
|
896
|
-
const
|
|
897
|
-
|
|
898
|
-
} = useRouter();
|
|
899
|
-
// return useStore(router.__store, opts?.select as any)
|
|
900
|
-
return opts?.select ? opts.select(state) : state;
|
|
898
|
+
const router = useRouter();
|
|
899
|
+
return useStore(router.__store, opts?.select);
|
|
901
900
|
}
|
|
902
901
|
function useRouter() {
|
|
903
902
|
const resolvedContext = typeof document !== 'undefined' ? window.__TSR_ROUTER_CONTEXT__ || routerContext : routerContext;
|
|
@@ -1260,9 +1259,6 @@ class Router {
|
|
|
1260
1259
|
// by the router provider once rendered. We provide these so that the
|
|
1261
1260
|
// router can be used in a non-react environment if necessary
|
|
1262
1261
|
startReactTransition = fn => fn();
|
|
1263
|
-
setState = updater => {
|
|
1264
|
-
this.state = functionalUpdate(updater, this.state);
|
|
1265
|
-
};
|
|
1266
1262
|
update = newOptions => {
|
|
1267
1263
|
this.options = {
|
|
1268
1264
|
...this.options,
|
|
@@ -1277,10 +1273,20 @@ class Router {
|
|
|
1277
1273
|
this.routeTree = this.options.routeTree;
|
|
1278
1274
|
this.buildRouteTree();
|
|
1279
1275
|
}
|
|
1280
|
-
if (!this.
|
|
1281
|
-
this.
|
|
1276
|
+
if (!this.__store) {
|
|
1277
|
+
this.__store = new Store(getInitialRouterState(this.latestLocation), {
|
|
1278
|
+
onUpdate: () => {
|
|
1279
|
+
this.__store.state = {
|
|
1280
|
+
...this.state,
|
|
1281
|
+
status: this.state.isTransitioning || this.state.isLoading ? 'pending' : 'idle'
|
|
1282
|
+
};
|
|
1283
|
+
}
|
|
1284
|
+
});
|
|
1282
1285
|
}
|
|
1283
1286
|
};
|
|
1287
|
+
get state() {
|
|
1288
|
+
return this.__store.state;
|
|
1289
|
+
}
|
|
1284
1290
|
buildRouteTree = () => {
|
|
1285
1291
|
this.routesById = {};
|
|
1286
1292
|
this.routesByPath = {};
|
|
@@ -1552,7 +1558,7 @@ class Router {
|
|
|
1552
1558
|
getRouteMatch(this.state, id)?.abortController?.abort();
|
|
1553
1559
|
};
|
|
1554
1560
|
cancelMatches = () => {
|
|
1555
|
-
this.state.
|
|
1561
|
+
this.state.pendingMatches?.forEach(match => {
|
|
1556
1562
|
this.cancelMatch(match.id);
|
|
1557
1563
|
});
|
|
1558
1564
|
};
|
|
@@ -1743,6 +1749,12 @@ class Router {
|
|
|
1743
1749
|
}) => {
|
|
1744
1750
|
let latestPromise;
|
|
1745
1751
|
let firstBadMatchIndex;
|
|
1752
|
+
const updatePendingMatch = match => {
|
|
1753
|
+
this.__store.setState(s => ({
|
|
1754
|
+
...s,
|
|
1755
|
+
pendingMatches: s.pendingMatches?.map(d => d.id === match.id ? match : d)
|
|
1756
|
+
}));
|
|
1757
|
+
};
|
|
1746
1758
|
|
|
1747
1759
|
// Check each match middleware to see if the route can be accessed
|
|
1748
1760
|
try {
|
|
@@ -1899,12 +1911,10 @@ class Router {
|
|
|
1899
1911
|
loadPromise
|
|
1900
1912
|
};
|
|
1901
1913
|
if (!preload) {
|
|
1902
|
-
|
|
1903
|
-
...s,
|
|
1904
|
-
matches: s.matches.map(d => d.id === match.id ? match : d)
|
|
1905
|
-
}));
|
|
1914
|
+
updatePendingMatch(match);
|
|
1906
1915
|
}
|
|
1907
1916
|
let didShowPending = false;
|
|
1917
|
+
const pendingMinMs = route.options.pendingMinMs ?? this.options.defaultPendingMinMs;
|
|
1908
1918
|
await new Promise(async resolve => {
|
|
1909
1919
|
// If the route has a pending component and a pendingMs option,
|
|
1910
1920
|
// forcefully show the pending component
|
|
@@ -1916,17 +1926,13 @@ class Router {
|
|
|
1916
1926
|
...match,
|
|
1917
1927
|
showPending: true
|
|
1918
1928
|
};
|
|
1919
|
-
|
|
1920
|
-
...s,
|
|
1921
|
-
matches: s.matches.map(d => d.id === match.id ? match : d)
|
|
1922
|
-
}));
|
|
1929
|
+
updatePendingMatch(match);
|
|
1923
1930
|
resolve();
|
|
1924
1931
|
});
|
|
1925
1932
|
}
|
|
1926
1933
|
try {
|
|
1927
1934
|
const loaderData = await loadPromise;
|
|
1928
1935
|
if (latestPromise = checkLatest()) return await latestPromise;
|
|
1929
|
-
const pendingMinMs = route.options.pendingMinMs ?? this.options.defaultPendingMinMs;
|
|
1930
1936
|
if (didShowPending && pendingMinMs) {
|
|
1931
1937
|
await new Promise(r => setTimeout(r, pendingMinMs));
|
|
1932
1938
|
}
|
|
@@ -1956,12 +1962,19 @@ class Router {
|
|
|
1956
1962
|
isFetching: false,
|
|
1957
1963
|
updatedAt: Date.now()
|
|
1958
1964
|
};
|
|
1965
|
+
} finally {
|
|
1966
|
+
// If we showed the pending component, that means
|
|
1967
|
+
// we already moved the pendingMatches to the matches
|
|
1968
|
+
// state, so we need to update that specific match
|
|
1969
|
+
if (didShowPending && pendingMinMs && match.showPending) {
|
|
1970
|
+
this.__store.setState(s => ({
|
|
1971
|
+
...s,
|
|
1972
|
+
matches: s.matches?.map(d => d.id === match.id ? match : d)
|
|
1973
|
+
}));
|
|
1974
|
+
}
|
|
1959
1975
|
}
|
|
1960
1976
|
if (!preload) {
|
|
1961
|
-
|
|
1962
|
-
...s,
|
|
1963
|
-
matches: s.matches.map(d => d.id === match.id ? match : d)
|
|
1964
|
-
}));
|
|
1977
|
+
updatePendingMatch(match);
|
|
1965
1978
|
}
|
|
1966
1979
|
resolve();
|
|
1967
1980
|
});
|
|
@@ -1990,24 +2003,23 @@ class Router {
|
|
|
1990
2003
|
});
|
|
1991
2004
|
|
|
1992
2005
|
// Match the routes
|
|
1993
|
-
let
|
|
2006
|
+
let pendingMatches = this.matchRoutes(next.pathname, next.search, {
|
|
1994
2007
|
debug: true
|
|
1995
2008
|
});
|
|
1996
|
-
this.pendingMatches = matches;
|
|
1997
2009
|
const previousMatches = this.state.matches;
|
|
1998
2010
|
|
|
1999
2011
|
// Ingest the new matches
|
|
2000
|
-
this.setState(s => ({
|
|
2012
|
+
this.__store.setState(s => ({
|
|
2001
2013
|
...s,
|
|
2002
|
-
|
|
2014
|
+
isLoading: true,
|
|
2003
2015
|
location: next,
|
|
2004
|
-
|
|
2016
|
+
pendingMatches
|
|
2005
2017
|
}));
|
|
2006
2018
|
try {
|
|
2007
2019
|
try {
|
|
2008
2020
|
// Load the matches
|
|
2009
2021
|
await this.loadMatches({
|
|
2010
|
-
matches,
|
|
2022
|
+
matches: pendingMatches,
|
|
2011
2023
|
checkLatest: () => this.checkLatest(promise),
|
|
2012
2024
|
invalidate: opts?.invalidate
|
|
2013
2025
|
});
|
|
@@ -2022,14 +2034,13 @@ class Router {
|
|
|
2022
2034
|
}
|
|
2023
2035
|
const exitingMatchIds = previousMatches.filter(id => !this.pendingMatches.includes(id));
|
|
2024
2036
|
const enteringMatchIds = this.pendingMatches.filter(id => !previousMatches.includes(id));
|
|
2025
|
-
const stayingMatchIds = previousMatches.filter(id => this.pendingMatches.includes(id))
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
// }))
|
|
2037
|
+
const stayingMatchIds = previousMatches.filter(id => this.pendingMatches.includes(id));
|
|
2038
|
+
this.__store.setState(s => ({
|
|
2039
|
+
...s,
|
|
2040
|
+
isLoading: false,
|
|
2041
|
+
matches: pendingMatches,
|
|
2042
|
+
pendingMatches: undefined
|
|
2043
|
+
}))
|
|
2033
2044
|
|
|
2034
2045
|
//
|
|
2035
2046
|
;
|
|
@@ -2184,9 +2195,6 @@ class Router {
|
|
|
2184
2195
|
return false;
|
|
2185
2196
|
}
|
|
2186
2197
|
const baseLocation = opts?.pending ? this.latestLocation : this.state.resolvedLocation;
|
|
2187
|
-
|
|
2188
|
-
// const baseLocation = state.resolvedLocation
|
|
2189
|
-
|
|
2190
2198
|
if (!baseLocation) {
|
|
2191
2199
|
return false;
|
|
2192
2200
|
}
|
|
@@ -2258,7 +2266,7 @@ class Router {
|
|
|
2258
2266
|
}
|
|
2259
2267
|
return match;
|
|
2260
2268
|
});
|
|
2261
|
-
this.setState(s => {
|
|
2269
|
+
this.__store.setState(s => {
|
|
2262
2270
|
return {
|
|
2263
2271
|
...s,
|
|
2264
2272
|
matches: matches
|
|
@@ -2289,6 +2297,8 @@ class SearchParamError extends Error {}
|
|
|
2289
2297
|
class PathParamError extends Error {}
|
|
2290
2298
|
function getInitialRouterState(location) {
|
|
2291
2299
|
return {
|
|
2300
|
+
isLoading: false,
|
|
2301
|
+
isTransitioning: false,
|
|
2292
2302
|
status: 'idle',
|
|
2293
2303
|
resolvedLocation: location,
|
|
2294
2304
|
location,
|