# Typed React Hooks

> The generated TanStack Query hooks — fully typed, one set per model.

The generator emits one hook set per model from the OpenAPI contract. Every hook is fully typed against the resource's fields, and every query key is derived so caching and invalidation just work.

```tsx title="app/airports.tsx"
import {
  useListAirports,
  useAirport,
  useCreateAirport,
  useUpdateAirport,
  useDeleteAirport,
} from "@/entities";

// List with typed filters and the DRF-shaped envelope.
const { data, isLoading } = useListAirports({ country: "JP" });
data?.results.forEach((a) => a.code /* string */);

// Read one.
const { data: airport } = useAirport(id);

// Mutate — optimistic, with automatic cache invalidation.
const create = useCreateAirport();
create.mutate({ code: "HND", name: "Haneda" });
```

## The list envelope

List endpoints return a Django-REST-Framework-shaped envelope, so pagination is consistent across every model:

```ts title="generated types"
type ListResponse<T> = {
  count: number;
  next: string | null;
  previous: string | null;
  results: T[];
};
```

## Built on TanStack Query

The hooks are thin, typed wrappers over [TanStack Query](https://tanstack.com/query), so you get caching, background refetching, and mutation lifecycles for free. What is unusual is that **the same hooks run against three completely different backends** without changing a line — the provider decides which.

> **Tip:** Continue to [Provider & Runtime Modes](https://reactapistack.com/docs/provider.md) to see how one setting relocates the whole engine.

---

_Source: [https://reactapistack.com/docs/hooks](https://reactapistack.com/docs/hooks) · Full docs as one file: [llms-full.txt](https://reactapistack.com/llms-full.txt)_
