react-router 0.0.0-experimental-af76d50e → 0.0.0-experimental-dc8656c8
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/CHANGELOG.md +25 -0
- package/LICENSE.md +3 -2
- package/README.md +2 -2
- package/dist/index.js +72 -37
- package/dist/index.js.map +1 -1
- package/dist/lib/context.d.ts +1 -0
- package/dist/main.js +1 -1
- package/dist/react-router.development.js +72 -38
- package/dist/react-router.development.js.map +1 -1
- package/dist/react-router.production.min.js +2 -2
- package/dist/react-router.production.min.js.map +1 -1
- package/dist/umd/react-router.development.js +76 -41
- package/dist/umd/react-router.development.js.map +1 -1
- package/dist/umd/react-router.production.min.js +2 -2
- package/dist/umd/react-router.production.min.js.map +1 -1
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,30 @@
|
|
|
1
1
|
# `react-router`
|
|
2
2
|
|
|
3
|
+
## 6.11.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Fix usage of `Component` API within descendant `<Routes>` ([#10434](https://github.com/remix-run/react-router/pull/10434))
|
|
8
|
+
- Fix bug when calling `useNavigate` from `<Routes>` inside a `<RouterProvider>` ([#10432](https://github.com/remix-run/react-router/pull/10432))
|
|
9
|
+
- Fix usage of `<Navigate>` in strict mode when using a data router ([#10435](https://github.com/remix-run/react-router/pull/10435))
|
|
10
|
+
- Updated dependencies:
|
|
11
|
+
- `@remix-run/router@1.6.1`
|
|
12
|
+
|
|
13
|
+
## 6.11.0
|
|
14
|
+
|
|
15
|
+
### Patch Changes
|
|
16
|
+
|
|
17
|
+
- Log loader/action errors to the console in dev for easier stack trace evaluation ([#10286](https://github.com/remix-run/react-router/pull/10286))
|
|
18
|
+
- Fix bug preventing rendering of descendant `<Routes>` when `RouterProvider` errors existed ([#10374](https://github.com/remix-run/react-router/pull/10374))
|
|
19
|
+
- Fix inadvertent re-renders when using `Component` instead of `element` on a route definition ([#10287](https://github.com/remix-run/react-router/pull/10287))
|
|
20
|
+
- Fix detection of `useNavigate` in the render cycle by setting the `activeRef` in a layout effect, allowing the `navigate` function to be passed to child components and called in a `useEffect` there. ([#10394](https://github.com/remix-run/react-router/pull/10394))
|
|
21
|
+
- Switched from `useSyncExternalStore` to `useState` for internal `@remix-run/router` router state syncing in `<RouterProvider>`. We found some [subtle bugs](https://codesandbox.io/s/use-sync-external-store-loop-9g7b81) where router state updates got propagated _before_ other normal `useState` updates, which could lead to footguns in `useEffect` calls. ([#10377](https://github.com/remix-run/react-router/pull/10377), [#10409](https://github.com/remix-run/react-router/pull/10409))
|
|
22
|
+
- Allow `useRevalidator()` to resolve a loader-driven error boundary scenario ([#10369](https://github.com/remix-run/react-router/pull/10369))
|
|
23
|
+
- Avoid unnecessary unsubscribe/resubscribes on router state changes ([#10409](https://github.com/remix-run/react-router/pull/10409))
|
|
24
|
+
- When using a `RouterProvider`, `useNavigate`/`useSubmit`/`fetcher.submit` are now stable across location changes, since we can handle relative routing via the `@remix-run/router` instance and get rid of our dependence on `useLocation()`. When using `BrowserRouter`, these hooks remain unstable across location changes because they still rely on `useLocation()`. ([#10336](https://github.com/remix-run/react-router/pull/10336))
|
|
25
|
+
- Updated dependencies:
|
|
26
|
+
- `@remix-run/router@1.6.0`
|
|
27
|
+
|
|
3
28
|
## 6.10.0
|
|
4
29
|
|
|
5
30
|
### Minor Changes
|
package/LICENSE.md
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
MIT License
|
|
2
2
|
|
|
3
|
-
Copyright (c) React Training 2015-2019
|
|
4
|
-
Copyright (c) Remix Software 2020-
|
|
3
|
+
Copyright (c) React Training LLC 2015-2019
|
|
4
|
+
Copyright (c) Remix Software Inc. 2020-2021
|
|
5
|
+
Copyright (c) Shopify Inc. 2022-2023
|
|
5
6
|
|
|
6
7
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
8
|
of this software and associated documentation files (the "Software"), to deal
|
package/README.md
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
The `react-router` package is the heart of [React Router](https://github.com/remix-run/react-router) and provides all
|
|
4
4
|
the core functionality for both
|
|
5
|
-
[`react-router-dom`](/packages/react-router-dom)
|
|
5
|
+
[`react-router-dom`](https://github.com/remix-run/react-router/tree/main/packages/react-router-dom)
|
|
6
6
|
and
|
|
7
|
-
[`react-router-native`](/packages/react-router-native).
|
|
7
|
+
[`react-router-native`](https://github.com/remix-run/react-router/tree/main/packages/react-router-native).
|
|
8
8
|
|
|
9
9
|
If you're using React Router, you should never `import` anything directly from
|
|
10
10
|
the `react-router` package, but you should have everything you need in either
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* React Router v0.0.0-experimental-
|
|
2
|
+
* React Router v0.0.0-experimental-dc8656c8
|
|
3
3
|
*
|
|
4
4
|
* Copyright (c) Remix Software Inc.
|
|
5
5
|
*
|
|
@@ -61,7 +61,8 @@ if (process.env.NODE_ENV !== "production") {
|
|
|
61
61
|
|
|
62
62
|
const RouteContext = /*#__PURE__*/React.createContext({
|
|
63
63
|
outlet: null,
|
|
64
|
-
matches: []
|
|
64
|
+
matches: [],
|
|
65
|
+
isDataRoute: false
|
|
65
66
|
});
|
|
66
67
|
|
|
67
68
|
if (process.env.NODE_ENV !== "production") {
|
|
@@ -171,23 +172,40 @@ function useMatch(pattern) {
|
|
|
171
172
|
* The interface for the navigate() function returned from useNavigate().
|
|
172
173
|
*/
|
|
173
174
|
|
|
175
|
+
const navigateEffectWarning = "You should call navigate() in a React.useEffect(), not when " + "your component is first rendered."; // Mute warnings for calls to useNavigate in SSR environments
|
|
176
|
+
|
|
177
|
+
function useIsomorphicLayoutEffect(cb) {
|
|
178
|
+
let isStatic = React.useContext(NavigationContext).static;
|
|
179
|
+
|
|
180
|
+
if (!isStatic) {
|
|
181
|
+
// We should be able to get rid of this once react 18.3 is released
|
|
182
|
+
// See: https://github.com/facebook/react/pull/26395
|
|
183
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
184
|
+
React.useLayoutEffect(cb);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
174
187
|
/**
|
|
175
188
|
* Returns an imperative method for changing the location. Used by <Link>s, but
|
|
176
189
|
* may also be used by other elements to change the location.
|
|
177
190
|
*
|
|
178
191
|
* @see https://reactrouter.com/hooks/use-navigate
|
|
179
192
|
*/
|
|
193
|
+
|
|
194
|
+
|
|
180
195
|
function useNavigate() {
|
|
181
|
-
let
|
|
196
|
+
let {
|
|
197
|
+
isDataRoute
|
|
198
|
+
} = React.useContext(RouteContext); // Conditional usage is OK here because the usage of a data router is static
|
|
182
199
|
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
183
200
|
|
|
184
|
-
return
|
|
201
|
+
return isDataRoute ? useNavigateStable() : useNavigateUnstable();
|
|
185
202
|
}
|
|
186
203
|
|
|
187
204
|
function useNavigateUnstable() {
|
|
188
205
|
!useInRouterContext() ? process.env.NODE_ENV !== "production" ? UNSAFE_invariant(false, // TODO: This error is probably because they somehow have 2 versions of the
|
|
189
206
|
// router loaded. We can help them understand how to avoid that.
|
|
190
207
|
"useNavigate() may be used only in the context of a <Router> component.") : UNSAFE_invariant(false) : void 0;
|
|
208
|
+
let dataRouterContext = React.useContext(DataRouterContext);
|
|
191
209
|
let {
|
|
192
210
|
basename,
|
|
193
211
|
navigator
|
|
@@ -200,7 +218,7 @@ function useNavigateUnstable() {
|
|
|
200
218
|
} = useLocation();
|
|
201
219
|
let routePathnamesJson = JSON.stringify(UNSAFE_getPathContributingMatches(matches).map(match => match.pathnameBase));
|
|
202
220
|
let activeRef = React.useRef(false);
|
|
203
|
-
|
|
221
|
+
useIsomorphicLayoutEffect(() => {
|
|
204
222
|
activeRef.current = true;
|
|
205
223
|
});
|
|
206
224
|
let navigate = React.useCallback(function (to, options) {
|
|
@@ -208,7 +226,9 @@ function useNavigateUnstable() {
|
|
|
208
226
|
options = {};
|
|
209
227
|
}
|
|
210
228
|
|
|
211
|
-
process.env.NODE_ENV !== "production" ? UNSAFE_warning(activeRef.current,
|
|
229
|
+
process.env.NODE_ENV !== "production" ? UNSAFE_warning(activeRef.current, navigateEffectWarning) : void 0; // Short circuit here since if this happens on first render the navigate
|
|
230
|
+
// is useless because we haven't wired up our history listener yet
|
|
231
|
+
|
|
212
232
|
if (!activeRef.current) return;
|
|
213
233
|
|
|
214
234
|
if (typeof to === "number") {
|
|
@@ -217,16 +237,18 @@ function useNavigateUnstable() {
|
|
|
217
237
|
}
|
|
218
238
|
|
|
219
239
|
let path = resolveTo(to, JSON.parse(routePathnamesJson), locationPathname, options.relative === "path"); // If we're operating within a basename, prepend it to the pathname prior
|
|
220
|
-
// to handing off to history
|
|
221
|
-
//
|
|
222
|
-
//
|
|
240
|
+
// to handing off to history (but only if we're not in a data router,
|
|
241
|
+
// otherwise it'll prepend the basename inside of the router).
|
|
242
|
+
// If this is a root navigation, then we navigate to the raw basename
|
|
243
|
+
// which allows the basename to have full control over the presence of a
|
|
244
|
+
// trailing slash on root links
|
|
223
245
|
|
|
224
|
-
if (basename !== "/") {
|
|
246
|
+
if (dataRouterContext == null && basename !== "/") {
|
|
225
247
|
path.pathname = path.pathname === "/" ? basename : joinPaths([basename, path.pathname]);
|
|
226
248
|
}
|
|
227
249
|
|
|
228
250
|
(!!options.replace ? navigator.replace : navigator.push)(path, options.state, options);
|
|
229
|
-
}, [basename, navigator, routePathnamesJson, locationPathname]);
|
|
251
|
+
}, [basename, navigator, routePathnamesJson, locationPathname, dataRouterContext]);
|
|
230
252
|
return navigate;
|
|
231
253
|
}
|
|
232
254
|
|
|
@@ -558,6 +580,14 @@ function _renderMatches(matches, parentMatches, dataRouterState) {
|
|
|
558
580
|
|
|
559
581
|
if (error) {
|
|
560
582
|
children = errorElement;
|
|
583
|
+
} else if (match.route.Component) {
|
|
584
|
+
// Note: This is a de-optimized path since React won't re-use the
|
|
585
|
+
// ReactElement since it's identity changes with each new
|
|
586
|
+
// React.createElement call. We keep this so folks can use
|
|
587
|
+
// `<Route Component={...}>` in `<Routes>` but generally `Component`
|
|
588
|
+
// usage is only advised in `RouterProvider` when we can convert it to
|
|
589
|
+
// `element` ahead of time.
|
|
590
|
+
children = /*#__PURE__*/React.createElement(match.route.Component, null);
|
|
561
591
|
} else if (match.route.element) {
|
|
562
592
|
children = match.route.element;
|
|
563
593
|
} else {
|
|
@@ -568,7 +598,8 @@ function _renderMatches(matches, parentMatches, dataRouterState) {
|
|
|
568
598
|
match: match,
|
|
569
599
|
routeContext: {
|
|
570
600
|
outlet,
|
|
571
|
-
matches
|
|
601
|
+
matches,
|
|
602
|
+
isDataRoute: dataRouterState != null
|
|
572
603
|
},
|
|
573
604
|
children: children
|
|
574
605
|
});
|
|
@@ -585,7 +616,8 @@ function _renderMatches(matches, parentMatches, dataRouterState) {
|
|
|
585
616
|
children: getChildren(),
|
|
586
617
|
routeContext: {
|
|
587
618
|
outlet: null,
|
|
588
|
-
matches
|
|
619
|
+
matches,
|
|
620
|
+
isDataRoute: true
|
|
589
621
|
}
|
|
590
622
|
}) : getChildren();
|
|
591
623
|
}, null);
|
|
@@ -803,11 +835,20 @@ function useNavigateStable() {
|
|
|
803
835
|
router
|
|
804
836
|
} = useDataRouterContext(DataRouterHook.UseNavigateStable);
|
|
805
837
|
let id = useCurrentRouteId(DataRouterStateHook.UseNavigateStable);
|
|
838
|
+
let activeRef = React.useRef(false);
|
|
839
|
+
useIsomorphicLayoutEffect(() => {
|
|
840
|
+
activeRef.current = true;
|
|
841
|
+
});
|
|
806
842
|
let navigate = React.useCallback(function (to, options) {
|
|
807
843
|
if (options === void 0) {
|
|
808
844
|
options = {};
|
|
809
845
|
}
|
|
810
846
|
|
|
847
|
+
process.env.NODE_ENV !== "production" ? UNSAFE_warning(activeRef.current, navigateEffectWarning) : void 0; // Short circuit here since if this happens on first render the navigate
|
|
848
|
+
// is useless because we haven't wired up our router subscriber yet
|
|
849
|
+
|
|
850
|
+
if (!activeRef.current) return;
|
|
851
|
+
|
|
811
852
|
if (typeof to === "number") {
|
|
812
853
|
router.navigate(to);
|
|
813
854
|
} else {
|
|
@@ -836,16 +877,10 @@ function RouterProvider(_ref) {
|
|
|
836
877
|
fallbackElement,
|
|
837
878
|
router
|
|
838
879
|
} = _ref;
|
|
839
|
-
|
|
880
|
+
// Need to use a layout effect here so we are subscribed early enough to
|
|
840
881
|
// pick up on any render-driven redirects/navigations (useEffect/<Navigate>)
|
|
841
|
-
|
|
842
|
-
React.useLayoutEffect(() =>
|
|
843
|
-
return router.subscribe(newState => {
|
|
844
|
-
if (newState !== state) {
|
|
845
|
-
setState(newState);
|
|
846
|
-
}
|
|
847
|
-
});
|
|
848
|
-
}, [router, state]);
|
|
882
|
+
let [state, setState] = React.useState(router.state);
|
|
883
|
+
React.useLayoutEffect(() => router.subscribe(setState), [router, setState]);
|
|
849
884
|
let navigator = React.useMemo(() => {
|
|
850
885
|
return {
|
|
851
886
|
createHref: router.createHref,
|
|
@@ -955,22 +990,22 @@ function Navigate(_ref4) {
|
|
|
955
990
|
// the router loaded. We can help them understand how to avoid that.
|
|
956
991
|
"<Navigate> may be used only in the context of a <Router> component.") : UNSAFE_invariant(false) : void 0;
|
|
957
992
|
process.env.NODE_ENV !== "production" ? UNSAFE_warning(!React.useContext(NavigationContext).static, "<Navigate> must not be used on the initial render in a <StaticRouter>. " + "This is a no-op, but you should modify your code so the <Navigate> is " + "only ever rendered in response to some user interaction or state change.") : void 0;
|
|
958
|
-
let
|
|
959
|
-
|
|
960
|
-
React.
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
}
|
|
993
|
+
let {
|
|
994
|
+
matches
|
|
995
|
+
} = React.useContext(RouteContext);
|
|
996
|
+
let {
|
|
997
|
+
pathname: locationPathname
|
|
998
|
+
} = useLocation();
|
|
999
|
+
let navigate = useNavigate(); // Resolve the path outside of the effect so that when effects run twice in
|
|
1000
|
+
// StrictMode they navigate to the same place
|
|
967
1001
|
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
1002
|
+
let path = resolveTo(to, UNSAFE_getPathContributingMatches(matches).map(match => match.pathnameBase), locationPathname, relative === "path");
|
|
1003
|
+
let jsonPath = JSON.stringify(path);
|
|
1004
|
+
React.useEffect(() => navigate(JSON.parse(jsonPath), {
|
|
1005
|
+
replace,
|
|
1006
|
+
state,
|
|
1007
|
+
relative
|
|
1008
|
+
}), [navigate, jsonPath, relative, replace, state]);
|
|
974
1009
|
return null;
|
|
975
1010
|
}
|
|
976
1011
|
|