Viewing docs for an older release. View latest
useFetcher
On this page

useFetcher

A hook for interacting with the server outside of navigation.

import { useFetcher } from "@remix-run/react";

export function SomeComponent() {
  const fetcher = useFetcher();
  // ...
}

Options

key

By default, useFetcher generate a unique fetcher scoped to that component (however, it may be looked up in useFetchers() while in-flight). 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:

function AddToBagButton() {
  const fetcher = useFetcher({ key: "add-to-bag" });
  return <fetcher.Form method="post">...</fetcher.Form>;
}

// Then, up in the header...
function CartCount({ count }) {
  const fetcher = useFetcher({ key: "add-to-bag" });
  const inFlightCount = Number(
    fetcher.formData?.get("quantity") || 0
  );
  const optimisticCount = count + inFlightCount;
  return (
    <>
      <BagIcon />
      <span>{optimisticCount}</span>
    </>
  );
}

Components

fetcher.Form

Just like <Form> except it doesn't cause a navigation.

function SomeComponent() {
  const fetcher = useFetcher();
  return (
    <fetcher.Form method="post" action="/some/route">
      <input type="text" />
    </fetcher.Form>
  );
}

Methods

fetcher.submit(formData, options)

Submits form data to a route. While multiple nested routes can match a URL, only the leaf route will be called.

The formData can be multiple types:

  • FormData - A FormData instance.
  • HTMLFormElement - A <form> DOM element.
  • Object - An object of key/value pairs that will be converted to a FormData instance.

If the method is GET, then the route loader is being called and with the formData serialized to the url as URLSearchParams. If DELETE, PATCH, POST, or PUT, then the route action is being called with formData as the body.

fetcher.submit(event.currentTarget.form, {
  method: "POST",
});

fetcher.submit(
  { serialized: "values" },
  { method: "POST" }
);

fetcher.submit(formData);

fetcher.submit is a wrapper around a useSubmit call for the fetcher instance, so it also accepts the same options as useSubmit.

fetcher.load(href, options)

Loads data from a route loader. While multiple nested routes can match a URL, only the leaf route will be called.

fetcher.load("/some/route");
fetcher.load("/some/route?foo=bar");

options.unstable_flushSync

The unstable_flushSync option tells React Router DOM to wrap the initial state update for this fetcher.load in a ReactDOM.flushSync call instead of the default React.startTransition. This allows you to perform synchronous DOM actions immediately after the update is flushed to the DOM.

ReactDOM.flushSync de-optimizes React and can hurt the performance of your app.

Properties

fetcher.state

You can know the state of the fetcher with fetcher.state. It will be one of:

  • idle - Nothing is being fetched.
  • submitting - A form has been submitted. If the method is GET, then the route loader is being called. If DELETE, PATCH, POST, or PUT, then the route action is being called.
  • loading - The loaders for the routes are being reloaded after an action submission.

fetcher.data

The returned response data from your action or loader is stored here. Once the data is set, it persists on the fetcher even through reloads and resubmissions (like calling fetcher.load() again after having already read the data).

fetcher.formData

The FormData instance that was submitted to the server is stored here. This is useful for optimistic UIs.

fetcher.formAction

The URL of the submission.

fetcher.formMethod

The form method of the submission.

Additional Resources

Discussions

Videos

Docs and examples licensed under MIT