diff --git a/contributors.yml b/contributors.yml index 441271bea7..d38281c5b3 100644 --- a/contributors.yml +++ b/contributors.yml @@ -312,3 +312,4 @@ - yuleicul - zeromask1337 - zheng-chuang +- AlemTuzlak diff --git a/packages/react-router/lib/dom/lib.tsx b/packages/react-router/lib/dom/lib.tsx index 413bd4527e..91ace047d0 100644 --- a/packages/react-router/lib/dom/lib.tsx +++ b/packages/react-router/lib/dom/lib.tsx @@ -1798,6 +1798,7 @@ export type FetcherWithComponents = Fetcher & { */ export function useFetcher({ key, + action }: { /** By default, `useFetcher` generate a unique fetcher scoped to that component. If you want to identify a fetcher with your own key such that you can access it from elsewhere in your app, you can do that with the `key` option: @@ -1817,6 +1818,17 @@ export function useFetcher({ ``` */ key?: string; + /** + * The action to use for the fetcher submissions. If not provided, the action will be derived from the route. + * ```tsx + * function MyForm() { + * let fetcher = useFetcher({ action: "/login" }); + * // ... + * } + * ``` + * The example above will submit to `/login` when the form is submitted either via `fetcher.submit` or `fetcher.Form`. or fetch from `/login/ when load is called + */ + action?: string; } = {}): FetcherWithComponents> { let { router } = useDataRouterContext(DataRouterHook.UseFetcher); let state = useDataRouterState(DataRouterStateHook.UseFetcher); @@ -1848,34 +1860,34 @@ export function useFetcher({ let load = React.useCallback( async (href: string, opts?: { flushSync?: boolean }) => { invariant(routeId, "No routeId available for fetcher.load()"); - await router.fetch(fetcherKey, routeId, href, opts); + await router.fetch(fetcherKey, routeId, action ? action : href, opts); }, - [fetcherKey, routeId, router] + [fetcherKey, routeId, router, action] ); let submitImpl = useSubmit(); let submit = React.useCallback( async (target, opts) => { - await submitImpl(target, { + await submitImpl(action ? action : target, { ...opts, navigate: false, fetcherKey, }); }, - [fetcherKey, submitImpl] + [fetcherKey, submitImpl, action] ); let FetcherForm = React.useMemo(() => { let FetcherForm = React.forwardRef( (props, ref) => { return ( -
+ ); } ); FetcherForm.displayName = "fetcher.Form"; return FetcherForm; - }, [fetcherKey]); + }, [fetcherKey, action]); // Exposed FetcherWithComponents let fetcher = state.fetchers.get(fetcherKey) || IDLE_FETCHER;