Skip to content

Commit cc2b341

Browse files
committed
Updates to transition/fetcher back compat
1 parent 1d079f3 commit cc2b341

File tree

3 files changed

+68
-61
lines changed

3 files changed

+68
-61
lines changed

integration/transition-state-test.ts

+6
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,12 @@ test.describe("rendering", () => {
3131
import { Outlet, Scripts, useTransition } from "@remix-run/react";
3232
export default function() {
3333
const transition = useTransition();
34+
35+
// TODO: This seems to have some issues with StrictMode?
36+
// - Passes running only transition tests w/StrictMode
37+
// - Passes on full suite with fullyParallel:false w/StrictMode
38+
// - Fails on full suite with fullyParallel:true w/StrictMode
39+
// - Passes on full suite with fullyParallel:true w/o StrictMode
3440
const transitionsRef = useRef();
3541
const transitions = useMemo(() => {
3642
const savedTransitions = transitionsRef.current || [];

packages/remix-react/components.tsx

+60-60
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import type {
88
AgnosticDataRouteMatch,
99
AgnosticDataRouteObject,
1010
ErrorResponse,
11-
Fetcher as FetcherRR,
11+
Navigation,
1212
} from "@remix-run/router";
1313
import type {
1414
LinkProps,
@@ -957,7 +957,13 @@ export function useActionData<T = AppData>(): SerializeFrom<T> | undefined {
957957
*/
958958
export function useTransition(): Transition {
959959
let navigation = useNavigation();
960+
return React.useMemo(
961+
() => convertNavigationToTransition(navigation),
962+
[navigation]
963+
);
964+
}
960965

966+
function convertNavigationToTransition(navigation: Navigation): Transition {
961967
let { location, state, formMethod, formAction, formEncType, formData } =
962968
navigation;
963969

@@ -1020,13 +1026,27 @@ export function useTransition(): Transition {
10201026
};
10211027
return transition;
10221028
} else {
1029+
// The new router fixes a bug in useTransition where the submission
1030+
// "action" represents the request URL not the state of the <form> in
1031+
// the DOM. Back-port it here to maintain behavior, but useNavigation
1032+
// will fix this bug.
1033+
let url = new URL(formAction, window.location.origin);
1034+
1035+
// This typing override should be safe since this is only running for
1036+
// GET submissions and over in @remix-run/router we have an invariant
1037+
// if you have any non-string values in your FormData when we attempt
1038+
// to convert them to URLSearchParams
1039+
url.search = new URLSearchParams(
1040+
formData.entries() as unknown as [string, string][]
1041+
).toString();
1042+
10231043
// Actively "submitting" to a loader
10241044
let transition: TransitionStates["SubmittingLoader"] = {
10251045
location,
10261046
state: "submitting",
10271047
submission: {
10281048
method: formMethod.toUpperCase() as LoaderSubmission["method"],
1029-
action: formAction,
1049+
action: url.pathname + url.search,
10301050
encType: formEncType,
10311051
formData: formData,
10321052
key: location.key,
@@ -1107,7 +1127,17 @@ export function useTransition(): Transition {
11071127
*/
11081128
export function useFetchers(): Fetcher[] {
11091129
let fetchers = useFetchersRR();
1110-
return fetchers.map(convertRRFetcherToRemixFetcher);
1130+
return fetchers.map((f) =>
1131+
convertRouterFetcherToRemixFetcher({
1132+
state: f.state,
1133+
data: f.data,
1134+
formMethod: f.formMethod,
1135+
formAction: f.formAction,
1136+
formData: f.formData,
1137+
formEncType: f.formEncType,
1138+
" _hasFetcherDoneAnything ": f[" _hasFetcherDoneAnything "],
1139+
})
1140+
);
11111141
}
11121142

11131143
export type FetcherWithComponents<TData> = Fetcher<TData> & {
@@ -1128,23 +1158,28 @@ export function useFetcher<TData = any>(): FetcherWithComponents<
11281158
SerializeFrom<TData>
11291159
> {
11301160
let fetcherRR = useFetcherRR();
1131-
return convertRRFetcherToRemixFetcher(fetcherRR);
1161+
let remixFetcher = convertRouterFetcherToRemixFetcher({
1162+
state: fetcherRR.state,
1163+
data: fetcherRR.data,
1164+
formMethod: fetcherRR.formMethod,
1165+
formAction: fetcherRR.formAction,
1166+
formData: fetcherRR.formData,
1167+
formEncType: fetcherRR.formEncType,
1168+
" _hasFetcherDoneAnything ": fetcherRR[" _hasFetcherDoneAnything "],
1169+
});
1170+
return {
1171+
...remixFetcher,
1172+
load: fetcherRR.load,
1173+
submit: fetcherRR.submit,
1174+
Form: fetcherRR.Form,
1175+
};
11321176
}
11331177

1134-
function convertRRFetcherToRemixFetcher(
1135-
fetcherRR: ReturnType<typeof useFetcherRR>
1136-
) {
1137-
let {
1138-
state,
1139-
formMethod,
1140-
formAction,
1141-
formEncType,
1142-
formData,
1143-
data,
1144-
Form,
1145-
submit,
1146-
load,
1147-
} = fetcherRR;
1178+
function convertRouterFetcherToRemixFetcher(
1179+
fetcherRR: Omit<ReturnType<typeof useFetcherRR>, "load" | "submit" | "Form">
1180+
): Fetcher {
1181+
let { state, formMethod, formAction, formEncType, formData, data } =
1182+
fetcherRR;
11481183

11491184
let isActionSubmission =
11501185
formMethod != null &&
@@ -1158,20 +1193,10 @@ function convertRRFetcherToRemixFetcher(
11581193
submission: undefined,
11591194
data,
11601195
};
1161-
return {
1162-
Form,
1163-
submit,
1164-
load,
1165-
...fetcher,
1166-
};
1196+
return fetcher;
11671197
} else {
11681198
let fetcher: FetcherStates["Idle"] = IDLE_FETCHER;
1169-
return {
1170-
Form,
1171-
submit,
1172-
load,
1173-
...fetcher,
1174-
};
1199+
return fetcher;
11751200
}
11761201
}
11771202

@@ -1205,12 +1230,7 @@ function convertRRFetcherToRemixFetcher(
12051230
},
12061231
data: undefined,
12071232
};
1208-
return {
1209-
Form,
1210-
submit,
1211-
load,
1212-
...fetcher,
1213-
};
1233+
return fetcher;
12141234
} else {
12151235
invariant(false, "nope");
12161236
}
@@ -1242,12 +1262,7 @@ function convertRRFetcherToRemixFetcher(
12421262
},
12431263
data,
12441264
};
1245-
return {
1246-
Form,
1247-
submit,
1248-
load,
1249-
...fetcher,
1250-
};
1265+
return fetcher;
12511266
} else {
12521267
let fetcher: FetcherStates["LoadingActionRedirect"] = {
12531268
state,
@@ -1262,12 +1277,7 @@ function convertRRFetcherToRemixFetcher(
12621277
},
12631278
data: undefined,
12641279
};
1265-
return {
1266-
Form,
1267-
submit,
1268-
load,
1269-
...fetcher,
1270-
};
1280+
return fetcher;
12711281
}
12721282
} else {
12731283
// The new router fixes a bug in useTransition where the submission
@@ -1306,12 +1316,7 @@ function convertRRFetcherToRemixFetcher(
13061316
},
13071317
data: undefined,
13081318
};
1309-
return {
1310-
Form,
1311-
submit,
1312-
load,
1313-
...fetcher,
1314-
};
1319+
return fetcher;
13151320
}
13161321
}
13171322
}
@@ -1323,12 +1328,7 @@ function convertRRFetcherToRemixFetcher(
13231328
submission: undefined,
13241329
data: undefined,
13251330
};
1326-
return {
1327-
Form,
1328-
submit,
1329-
load,
1330-
...fetcher,
1331-
};
1331+
return fetcher;
13321332
}
13331333

13341334
// Dead Code Elimination magic for production builds.

packages/remix-server-runtime/server.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,8 @@ async function handleDocumentRequestRR(
259259
);
260260
} catch (error: unknown) {
261261
if (serverMode !== ServerMode.Test) {
262-
// TODO Do we want to log this here?
262+
// TODO Do we want to log this here? Can we get it to not log on
263+
// integration tests runs?
263264
console.log("Error in entry.server handleDocumentRequest:", error);
264265
}
265266

0 commit comments

Comments
 (0)