react-router-dom 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 +26 -0
- package/LICENSE.md +3 -2
- package/dist/dom.d.ts +9 -16
- package/dist/index.d.ts +7 -4
- package/dist/index.js +45 -62
- package/dist/index.js.map +1 -1
- package/dist/main.js +1 -1
- package/dist/react-router-dom.development.js +45 -62
- package/dist/react-router-dom.development.js.map +1 -1
- package/dist/react-router-dom.production.min.js +2 -2
- package/dist/react-router-dom.production.min.js.map +1 -1
- package/dist/server.js +2 -1
- package/dist/server.mjs +2 -1
- package/dist/umd/react-router-dom.development.js +45 -62
- package/dist/umd/react-router-dom.development.js.map +1 -1
- package/dist/umd/react-router-dom.production.min.js +2 -2
- package/dist/umd/react-router-dom.production.min.js.map +1 -1
- package/package.json +3 -3
- package/server.js +2 -1
- package/server.mjs +2 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,31 @@
|
|
|
1
1
|
# `react-router-dom`
|
|
2
2
|
|
|
3
|
+
## 6.11.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies:
|
|
8
|
+
- `react-router@6.11.1`
|
|
9
|
+
- `@remix-run/router@1.6.1`
|
|
10
|
+
|
|
11
|
+
## 6.11.0
|
|
12
|
+
|
|
13
|
+
### Minor Changes
|
|
14
|
+
|
|
15
|
+
- Enable `basename` support in `useFetcher` ([#10336](https://github.com/remix-run/react-router/pull/10336))
|
|
16
|
+
- If you were previously working around this issue by manually prepending the `basename` then you will need to remove the manually prepended `basename` from your `fetcher` calls (`fetcher.load('/basename/route') -> fetcher.load('/route')`)
|
|
17
|
+
|
|
18
|
+
### Patch Changes
|
|
19
|
+
|
|
20
|
+
- Fix inadvertent re-renders when using `Component` instead of `element` on a route definition ([#10287](https://github.com/remix-run/react-router/pull/10287))
|
|
21
|
+
- Fail gracefully on `<Link to="//">` and other invalid URL values ([#10367](https://github.com/remix-run/react-router/pull/10367))
|
|
22
|
+
- 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))
|
|
23
|
+
- Add static prop to `StaticRouterProvider`'s internal `Router` component ([#10401](https://github.com/remix-run/react-router/pull/10401))
|
|
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
|
+
- `react-router@6.11.0`
|
|
27
|
+
- `@remix-run/router@1.6.0`
|
|
28
|
+
|
|
3
29
|
## 6.10.0
|
|
4
30
|
|
|
5
31
|
### 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/dist/dom.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { FormEncType, HTMLFormMethod, RelativeRoutingType } from "@remix-run/router";
|
|
2
2
|
export declare const defaultMethod: HTMLFormMethod;
|
|
3
3
|
export declare function isHtmlElement(object: any): object is HTMLElement;
|
|
4
4
|
export declare function isButtonElement(object: any): object is HTMLButtonElement;
|
|
@@ -31,9 +31,6 @@ export declare type URLSearchParamsInit = string | ParamKeyValuePair[] | Record<
|
|
|
31
31
|
*/
|
|
32
32
|
export declare function createSearchParams(init?: URLSearchParamsInit): URLSearchParams;
|
|
33
33
|
export declare function getSearchParamsForLocation(locationSearch: string, defaultSearchParams: URLSearchParams | null): URLSearchParams;
|
|
34
|
-
export declare type SubmitTarget = HTMLFormElement | HTMLButtonElement | HTMLInputElement | FormData | URLSearchParams | {
|
|
35
|
-
[name: string]: string;
|
|
36
|
-
} | NonNullable<unknown> | null;
|
|
37
34
|
export interface SubmitOptions {
|
|
38
35
|
/**
|
|
39
36
|
* The HTTP method used to submit the form. Overrides `<form method>`.
|
|
@@ -44,17 +41,12 @@ export interface SubmitOptions {
|
|
|
44
41
|
* The action URL path used to submit the form. Overrides `<form action>`.
|
|
45
42
|
* Defaults to the path of the current route.
|
|
46
43
|
*/
|
|
47
|
-
action?: string
|
|
44
|
+
action?: string;
|
|
48
45
|
/**
|
|
49
46
|
* The action URL used to submit the form. Overrides `<form encType>`.
|
|
50
|
-
* Defaults to "application/x-www-form-urlencoded".
|
|
51
|
-
* opt-out of serialization and will submit the data directly to your action
|
|
52
|
-
* in the `payload` parameter.
|
|
53
|
-
*
|
|
54
|
-
* In v7, the default behavior will change from "application/x-www-form-urlencoded"
|
|
55
|
-
* to `null` and will make serialization opt-in
|
|
47
|
+
* Defaults to "application/x-www-form-urlencoded".
|
|
56
48
|
*/
|
|
57
|
-
encType?: FormEncType
|
|
49
|
+
encType?: FormEncType;
|
|
58
50
|
/**
|
|
59
51
|
* Set `true` to replace the current entry in the browser's history stack
|
|
60
52
|
* instead of creating a new one (i.e. stay on "the same page"). Defaults
|
|
@@ -73,11 +65,12 @@ export interface SubmitOptions {
|
|
|
73
65
|
*/
|
|
74
66
|
preventScrollReset?: boolean;
|
|
75
67
|
}
|
|
76
|
-
export declare function getFormSubmissionInfo(target:
|
|
68
|
+
export declare function getFormSubmissionInfo(target: HTMLFormElement | HTMLButtonElement | HTMLInputElement | FormData | URLSearchParams | {
|
|
69
|
+
[name: string]: string;
|
|
70
|
+
} | null, options: SubmitOptions, basename: string): {
|
|
77
71
|
action: string | null;
|
|
78
72
|
method: string;
|
|
79
|
-
encType: string
|
|
80
|
-
formData: FormData
|
|
81
|
-
payload: any;
|
|
73
|
+
encType: string;
|
|
74
|
+
formData: FormData;
|
|
82
75
|
};
|
|
83
76
|
export {};
|
package/dist/index.d.ts
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import * as React from "react";
|
|
6
6
|
import type { NavigateOptions, RelativeRoutingType, RouteObject, To } from "react-router";
|
|
7
|
-
import type { Fetcher, FormEncType, FormMethod, FutureConfig, GetScrollRestorationKeyFunction, History, HTMLFormMethod, HydrationState,
|
|
8
|
-
import type { SubmitOptions, ParamKeyValuePair, URLSearchParamsInit
|
|
7
|
+
import type { Fetcher, FormEncType, FormMethod, FutureConfig, GetScrollRestorationKeyFunction, History, HTMLFormMethod, HydrationState, Router as RemixRouter, V7_FormMethod } from "@remix-run/router";
|
|
8
|
+
import type { SubmitOptions, ParamKeyValuePair, URLSearchParamsInit } from "./dom";
|
|
9
9
|
import { createSearchParams } from "./dom";
|
|
10
10
|
export type { FormEncType, FormMethod, GetScrollRestorationKeyFunction, ParamKeyValuePair, SubmitOptions, URLSearchParamsInit, V7_FormMethod, };
|
|
11
11
|
export { createSearchParams };
|
|
@@ -164,7 +164,10 @@ export declare function useLinkClickHandler<E extends Element = HTMLAnchorElemen
|
|
|
164
164
|
* URLSearchParams interface.
|
|
165
165
|
*/
|
|
166
166
|
export declare function useSearchParams(defaultInit?: URLSearchParamsInit): [URLSearchParams, SetURLSearchParams];
|
|
167
|
-
declare type SetURLSearchParams = (nextInit?: URLSearchParamsInit | ((prev: URLSearchParams) => URLSearchParamsInit), navigateOpts?: NavigateOptions) => void;
|
|
167
|
+
export declare type SetURLSearchParams = (nextInit?: URLSearchParamsInit | ((prev: URLSearchParams) => URLSearchParamsInit), navigateOpts?: NavigateOptions) => void;
|
|
168
|
+
declare type SubmitTarget = HTMLFormElement | HTMLButtonElement | HTMLInputElement | FormData | URLSearchParams | {
|
|
169
|
+
[name: string]: string;
|
|
170
|
+
} | null;
|
|
168
171
|
/**
|
|
169
172
|
* Submits a HTML `<form>` to the server without reloading the page.
|
|
170
173
|
*/
|
|
@@ -197,7 +200,7 @@ declare function createFetcherForm(fetcherKey: string, routeId: string): React.F
|
|
|
197
200
|
export declare type FetcherWithComponents<TData> = Fetcher<TData> & {
|
|
198
201
|
Form: ReturnType<typeof createFetcherForm>;
|
|
199
202
|
submit: (target: SubmitTarget, options?: Omit<SubmitOptions, "replace" | "preventScrollReset">) => void;
|
|
200
|
-
load: (href: string
|
|
203
|
+
load: (href: string) => void;
|
|
201
204
|
};
|
|
202
205
|
/**
|
|
203
206
|
* Interacts with route loaders and actions without causing a navigation. Great
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* React Router DOM v0.0.0-experimental-
|
|
2
|
+
* React Router DOM v0.0.0-experimental-dc8656c8
|
|
3
3
|
*
|
|
4
4
|
* Copyright (c) Remix Software Inc.
|
|
5
5
|
*
|
|
@@ -117,37 +117,52 @@ function getSearchParamsForLocation(locationSearch, defaultSearchParams) {
|
|
|
117
117
|
|
|
118
118
|
return searchParams;
|
|
119
119
|
}
|
|
120
|
-
function getFormSubmissionInfo(target,
|
|
120
|
+
function getFormSubmissionInfo(target, options, basename) {
|
|
121
121
|
let method;
|
|
122
|
-
let action;
|
|
122
|
+
let action = null;
|
|
123
123
|
let encType;
|
|
124
|
-
let formData
|
|
125
|
-
let payload = undefined;
|
|
124
|
+
let formData;
|
|
126
125
|
|
|
127
126
|
if (isFormElement(target)) {
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
127
|
+
let submissionTrigger = options.submissionTrigger;
|
|
128
|
+
|
|
129
|
+
if (options.action) {
|
|
130
|
+
action = options.action;
|
|
131
|
+
} else {
|
|
132
|
+
// When grabbing the action from the element, it will have had the basename
|
|
133
|
+
// prefixed to ensure non-JS scenarios work, so strip it since we'll
|
|
134
|
+
// re-prefix in the router
|
|
135
|
+
let attr = target.getAttribute("action");
|
|
136
|
+
action = attr ? stripBasename(attr, basename) : null;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
method = options.method || target.getAttribute("method") || defaultMethod;
|
|
140
|
+
encType = options.encType || target.getAttribute("enctype") || defaultEncType;
|
|
135
141
|
formData = new FormData(target);
|
|
142
|
+
|
|
143
|
+
if (submissionTrigger && submissionTrigger.name) {
|
|
144
|
+
formData.append(submissionTrigger.name, submissionTrigger.value);
|
|
145
|
+
}
|
|
136
146
|
} else if (isButtonElement(target) || isInputElement(target) && (target.type === "submit" || target.type === "image")) {
|
|
137
147
|
let form = target.form;
|
|
138
148
|
|
|
139
149
|
if (form == null) {
|
|
140
150
|
throw new Error("Cannot submit a <button> or <input type=\"submit\"> without a <form>");
|
|
141
151
|
} // <button>/<input type="submit"> may override attributes of <form>
|
|
142
|
-
// When grabbing the action from the element, it will have had the basename
|
|
143
|
-
// prefixed to ensure non-JS scenarios work, so strip it since we'll
|
|
144
|
-
// re-prefix in the router
|
|
145
152
|
|
|
146
153
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
154
|
+
if (options.action) {
|
|
155
|
+
action = options.action;
|
|
156
|
+
} else {
|
|
157
|
+
// When grabbing the action from the element, it will have had the basename
|
|
158
|
+
// prefixed to ensure non-JS scenarios work, so strip it since we'll
|
|
159
|
+
// re-prefix in the router
|
|
160
|
+
let attr = target.getAttribute("formaction") || form.getAttribute("action");
|
|
161
|
+
action = attr ? stripBasename(attr, basename) : null;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
method = options.method || target.getAttribute("formmethod") || form.getAttribute("method") || defaultMethod;
|
|
165
|
+
encType = options.encType || target.getAttribute("formenctype") || form.getAttribute("enctype") || defaultEncType;
|
|
151
166
|
formData = new FormData(form); // Include name + value from a <button>, appending in case the button name
|
|
152
167
|
// matches an existing input name
|
|
153
168
|
|
|
@@ -156,22 +171,10 @@ function getFormSubmissionInfo(target, formEncType, basename) {
|
|
|
156
171
|
}
|
|
157
172
|
} else if (isHtmlElement(target)) {
|
|
158
173
|
throw new Error("Cannot submit element that is not <form>, <button>, or " + "<input type=\"submit|image\">");
|
|
159
|
-
} else if (formEncType !== undefined && formEncType !== "application/x-www-form-urlencoded") {
|
|
160
|
-
// The default behavior is to encode as application/x-www-form-urlencoded
|
|
161
|
-
// into FormData which is handled in the else block below.
|
|
162
|
-
//
|
|
163
|
-
// Any other encType value (null, application/json, text/plain) means
|
|
164
|
-
// we will not be submitting as FormData so send the payload through
|
|
165
|
-
// directly. The @remix-run/router will handle serialization of the
|
|
166
|
-
// payload upon Request creation if needed.
|
|
167
|
-
method = defaultMethod;
|
|
168
|
-
action = null;
|
|
169
|
-
encType = null;
|
|
170
|
-
payload = target;
|
|
171
174
|
} else {
|
|
172
|
-
method = defaultMethod;
|
|
173
|
-
action = null;
|
|
174
|
-
encType = defaultEncType;
|
|
175
|
+
method = options.method || defaultMethod;
|
|
176
|
+
action = options.action || null;
|
|
177
|
+
encType = options.encType || defaultEncType;
|
|
175
178
|
|
|
176
179
|
if (target instanceof FormData) {
|
|
177
180
|
formData = target;
|
|
@@ -183,14 +186,7 @@ function getFormSubmissionInfo(target, formEncType, basename) {
|
|
|
183
186
|
formData.append(name, value);
|
|
184
187
|
}
|
|
185
188
|
} else if (target != null) {
|
|
186
|
-
// When a raw object is sent - even though we encode it into formData,
|
|
187
|
-
// we still expose it as payload so it aligns with the behavior if
|
|
188
|
-
// encType were application/json or text/plain
|
|
189
|
-
payload = target; // To be deprecated in v7 so the default behavior of undefined matches
|
|
190
|
-
// the null behavior of no-serialization
|
|
191
|
-
|
|
192
189
|
for (let name of Object.keys(target)) {
|
|
193
|
-
// @ts-expect-error
|
|
194
190
|
formData.append(name, target[name]);
|
|
195
191
|
}
|
|
196
192
|
}
|
|
@@ -201,8 +197,7 @@ function getFormSubmissionInfo(target, formEncType, basename) {
|
|
|
201
197
|
action,
|
|
202
198
|
method: method.toLowerCase(),
|
|
203
199
|
encType,
|
|
204
|
-
formData
|
|
205
|
-
payload
|
|
200
|
+
formData
|
|
206
201
|
};
|
|
207
202
|
}
|
|
208
203
|
|
|
@@ -736,26 +731,21 @@ function useSubmitImpl(fetcherKey, fetcherRouteId) {
|
|
|
736
731
|
action,
|
|
737
732
|
method,
|
|
738
733
|
encType,
|
|
739
|
-
formData
|
|
740
|
-
|
|
741
|
-
} = getFormSubmissionInfo(target, options.encType, basename);
|
|
742
|
-
let path = typeof options.action === "function" ? null : options.action || action;
|
|
743
|
-
let routerAction = typeof options.action === "function" ? options.action : null; // Base options shared between fetch() and navigate()
|
|
734
|
+
formData
|
|
735
|
+
} = getFormSubmissionInfo(target, options, basename); // Base options shared between fetch() and navigate()
|
|
744
736
|
|
|
745
737
|
let opts = {
|
|
746
738
|
preventScrollReset: options.preventScrollReset,
|
|
747
739
|
formData,
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
formEncType: options.encType || encType,
|
|
751
|
-
action: routerAction
|
|
740
|
+
formMethod: method,
|
|
741
|
+
formEncType: encType
|
|
752
742
|
};
|
|
753
743
|
|
|
754
744
|
if (fetcherKey) {
|
|
755
745
|
!(fetcherRouteId != null) ? process.env.NODE_ENV !== "production" ? UNSAFE_invariant(false, "No routeId available for useFetcher()") : UNSAFE_invariant(false) : void 0;
|
|
756
|
-
router.fetch(fetcherKey, fetcherRouteId,
|
|
746
|
+
router.fetch(fetcherKey, fetcherRouteId, action, opts);
|
|
757
747
|
} else {
|
|
758
|
-
router.navigate(
|
|
748
|
+
router.navigate(action, _extends({}, opts, {
|
|
759
749
|
replace: options.replace,
|
|
760
750
|
fromRouteId: currentRouteId
|
|
761
751
|
}));
|
|
@@ -859,14 +849,7 @@ function useFetcher() {
|
|
|
859
849
|
let [load] = React.useState(() => href => {
|
|
860
850
|
!router ? process.env.NODE_ENV !== "production" ? UNSAFE_invariant(false, "No router available for fetcher.load()") : UNSAFE_invariant(false) : void 0;
|
|
861
851
|
!routeId ? process.env.NODE_ENV !== "production" ? UNSAFE_invariant(false, "No routeId available for fetcher.load()") : UNSAFE_invariant(false) : void 0;
|
|
862
|
-
|
|
863
|
-
if (typeof href === "function") {
|
|
864
|
-
router.fetch(fetcherKey, routeId, null, {
|
|
865
|
-
loader: href
|
|
866
|
-
});
|
|
867
|
-
} else {
|
|
868
|
-
router.fetch(fetcherKey, routeId, href);
|
|
869
|
-
}
|
|
852
|
+
router.fetch(fetcherKey, routeId, href);
|
|
870
853
|
});
|
|
871
854
|
let submit = useSubmitImpl(fetcherKey, routeId);
|
|
872
855
|
let fetcher = router.getFetcher(fetcherKey);
|