# Calling API Routes from Client with React Query

> Learn how to use React Query to call your API route handlers from React components

*Canonical: https://makerkit.dev/docs/remix-supabase/how-to/api/call-api-routes-from-client*

---

Makerkit includes the library React Query, a data-fetching React utility library.

This library is useful for making asynchronous requests from your React components. For example:

1. When interacting with the Supabase Client (DB, Storage, Auth, etc.)
2. When making requests to API Routes

Why is it useful? React Query makes it simpler to fetch and mutate data, caching and revalidating. Let's see how we can use it to make requests to our endpoints.

### Should I use React Query or Remix's useFetcher/useSubmit?

No exact answer - but here is what I do:

1. For actions that need to trigger a refresh of the UI, I use Remix's `useSubmit/useRefresh` hook.
2. For pulling data from the server-side as a result of user interactions, I use React Query.

Ultimately, you should use what you feel more comfortable with as both approaches are valid.

## Using React Query for fetching data from an API Route Handler

Let's assume we have a very simple API Route at `routes/resources.data.ts`:

 ```tsx {% title="app/routes/resources.data.ts" %}
import { json } from "@remix-run/node";

export async function loader() {
  return json({
    hello: "world"
  });
}
```

As you may know, we can call the endpoint `/resources/data` using a GET request and will receive the JSON response `{ "hello": "world" }`.

Now, we want to call this from our Remix application using React Query, and use
it within a React component.

We proceed building a React Hook with React Query which is able to fetch the data from our endpoint `/api/data`:

```tsx
import { useQuery } from '@tanstack/react-query';

export function useFetchData() {
  const key = '/api/data';

  return useQuery([key], async () => {
    return fetch(key).then(res => res.json())
  });
}
```

Now, we can call this endpoint from any React component:

```tsx
function MyComponent() {
  const { data, loading, error } = useFetchData();

  if (loading) {
    return <p>Loading...</p>;
  }

  if (error) {
    return <p>Error...</p>;
  }

  return <div>{data.hello}</div>
}
```

## Mutating data with React Query

When it comes to mutating data, we can use the `useMutation` utility, designed to make mutations simple.

As you may know, mutations will likely use the method `POST`, `PUT`, `PATCH`, or `DELETE`. In these cases, the middleware in the kit will require us to send a CSRF token for security reasons.

As such, we provide a handy wrapper around `fetch`.

Let's write a very simple API Route that makes a mutation: we add a new record in the `tasks` table, and return the ID back to the client.

```tsx
import { ActionFunctionArgs, json } from "@remix-run/node";

export async function action(args: ActionFunctionArgs) {
  const client = getSupabaseServerClient(args.request);
  const session = await requireSession(client);
  const task = args.request.json();

  const { data } = await client.from('tasks').insert({
    name: task.name,
    done: false,
    user_id: session.user.id,
  })
  .select('id')
  .single();

  return json({ id: data.id });
}
```

Now, let's write a React Hook that calls this endpoint using React Query.

```tsx
import { useMutation } from '@tanstack/react-query';
import useFetch from '~/core/hooks/use-fetch';

interface Task {
  name: string;
}

function useInsertTask() {
  const fetcher = useFetch();
  const path = '/api/task';

  return useMutation(
    path, async (data: Task) => {
      return fetcher({
        path,
        body: data,
        method: 'POST'
      });
    }
  );
}
```

What does `useFetch` do? This hook automatically inserts the CSRF token in our fetch requests, so that you don't have to.

If you prefer not using it, you can manually add the CSRF token instead:

```tsx
import { useMutation } from '@tanstack/react-query';
import useCsrfToken from '~/core/hooks/use-csrf-token';

interface Task {
  name: string;
}

function useInsertTask() {
  const csrfToken = useCsrfToken();
  const path = '/api/task';

  return useMutation((data: Task) => {
      return fetch(path, {
        body: JSON.stringify(data),
        method: 'POST',
        headers: {
          'x-csrf-token': csrfToken
        }
    });
  });
}
```

We can now call the mutation from a React component:

```tsx
function TaskForm() {
  const insertTaskMutation = useInsertTask();

  const onSubmit: React.FormEventHandler<HTMLFormElement> = (event) => {
    const name = new FormData(event.currentTarget).get('name') ?? 'No Name';
    const task = { name };

    return insertTaskMutation.mutateAsync(task);
  };

  return (
    <form onSubmit={onSubmit}>
      <input type={'name'} required />

      <button disabled={insertTaskMutation.loading}>
        Submit
      </button>
    </form>
  );
}
```
