Skip to content

Commit

Permalink
Fix fetcher.submit types (#11631)
Browse files Browse the repository at this point in the history
  • Loading branch information
brophdawg11 authored Jun 13, 2024
1 parent 3a27b1f commit be8a259
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 31 deletions.
5 changes: 5 additions & 0 deletions .changeset/gorgeous-geese-sit.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"react-router-dom": patch
---

Fix `fetcher.submit` types - remove incorrect `navigate`/`fetcherKey`/`unstable_viewTransition` options because they are only relevant for `useSubmit`
47 changes: 30 additions & 17 deletions packages/react-router-dom/dom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,10 @@ function isFormDataSubmitterSupported() {
return _formDataSupportsSubmitter;
}

export interface SubmitOptions {
/**
* Submit options shared by both navigations and fetchers
*/
interface SharedSubmitOptions {
/**
* The HTTP method used to submit the form. Overrides `<form method>`.
* Defaults to "GET".
Expand All @@ -170,15 +173,33 @@ export interface SubmitOptions {
encType?: FormEncType;

/**
* Indicate a specific fetcherKey to use when using navigate=false
* Determines whether the form action is relative to the route hierarchy or
* the pathname. Use this if you want to opt out of navigating the route
* hierarchy and want to instead route based on /-delimited URL segments
*/
fetcherKey?: string;
relative?: RelativeRoutingType;

/**
* navigate=false will use a fetcher instead of a navigation
* In browser-based environments, prevent resetting scroll after this
* navigation when using the <ScrollRestoration> component
*/
navigate?: boolean;
preventScrollReset?: boolean;

/**
* Enable flushSync for this submission's state updates
*/
unstable_flushSync?: boolean;
}

/**
* Submit options available to fetchers
*/
export interface FetcherSubmitOptions extends SharedSubmitOptions {}

/**
* Submit options available to navigations
*/
export interface SubmitOptions extends FetcherSubmitOptions {
/**
* Set `true` to replace the current entry in the browser's history stack
* instead of creating a new one (i.e. stay on "the same page"). Defaults
Expand All @@ -192,22 +213,14 @@ export interface SubmitOptions {
state?: any;

/**
* Determines whether the form action is relative to the route hierarchy or
* the pathname. Use this if you want to opt out of navigating the route
* hierarchy and want to instead route based on /-delimited URL segments
*/
relative?: RelativeRoutingType;

/**
* In browser-based environments, prevent resetting scroll after this
* navigation when using the <ScrollRestoration> component
* Indicate a specific fetcherKey to use when using navigate=false
*/
preventScrollReset?: boolean;
fetcherKey?: string;

/**
* Enable flushSync for this navigation's state updates
* navigate=false will use a fetcher instead of a navigation
*/
unstable_flushSync?: boolean;
navigate?: boolean;

/**
* Enable view transitions on this submission navigation
Expand Down
19 changes: 15 additions & 4 deletions packages/react-router-dom/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ import type {
ParamKeyValuePair,
URLSearchParamsInit,
SubmitTarget,
FetcherSubmitOptions,
} from "./dom";
import {
createSearchParams,
Expand Down Expand Up @@ -1158,8 +1159,10 @@ if (__DEV__) {
NavLink.displayName = "NavLink";
}

export interface FetcherFormProps
extends React.FormHTMLAttributes<HTMLFormElement> {
/**
* Form props shared by navigations and fetchers
*/
interface SharedFormProps extends React.FormHTMLAttributes<HTMLFormElement> {
/**
* The HTTP verb to use when the form is submit. Supports "get", "post",
* "put", "delete", "patch".
Expand Down Expand Up @@ -1200,7 +1203,15 @@ export interface FetcherFormProps
onSubmit?: React.FormEventHandler<HTMLFormElement>;
}

export interface FormProps extends FetcherFormProps {
/**
* Form props available to fetchers
*/
export interface FetcherFormProps extends SharedFormProps {}

/**
* Form props available to navigations
*/
export interface FormProps extends SharedFormProps {
/**
* Indicate a specific fetcherKey to use when using navigate=false
*/
Expand Down Expand Up @@ -1523,7 +1534,7 @@ export interface FetcherSubmitFunction {
(
target: SubmitTarget,
// Fetchers cannot replace or set state because they are not navigation events
options?: Omit<SubmitOptions, "replace" | "state">
options?: FetcherSubmitOptions
): void;
}

Expand Down
24 changes: 14 additions & 10 deletions packages/router/__tests__/navigation-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -169,11 +169,13 @@ describe("navigations", () => {
})
);
expect(t.router.state.loaderData).toEqual({});
expect(t.router.state.errors).toMatchInlineSnapshot(`
{
"foo": [SyntaxError: Unexpected token } in JSON at position 15],
}
`);

// Node 16/18 versus 20 output different errors here :/
let expected =
process.version.startsWith("v16") || process.version.startsWith("v18")
? "Unexpected token } in JSON at position 15"
: "Unexpected non-whitespace character after JSON at position 15";
expect(t.router.state.errors?.foo).toEqual(new SyntaxError(expected));
});

it("bubbles errors when unwrapping Responses", async () => {
Expand Down Expand Up @@ -204,11 +206,13 @@ describe("navigations", () => {
})
);
expect(t.router.state.loaderData).toEqual({});
expect(t.router.state.errors).toMatchInlineSnapshot(`
{
"root": [SyntaxError: Unexpected token } in JSON at position 15],
}
`);

// Node 16/18 versus 20 output different errors here :/
let expected =
process.version.startsWith("v16") || process.version.startsWith("v18")
? "Unexpected token } in JSON at position 15"
: "Unexpected non-whitespace character after JSON at position 15";
expect(t.router.state.errors?.root).toEqual(new SyntaxError(expected));
});

it("does not fetch unchanging layout data", async () => {
Expand Down

0 comments on commit be8a259

Please sign in to comment.