# Hooks

URL: https://developers.uidu.org/docs/tools/react/hooks

> React hooks for fetching uidu data on the client, accessing the client, and normalizing CMS data.

`useQuery` fetches data in Client Components. `useUiduClient` and `useUidu` read the client from context. `useFields` and `toText` are pure transforms for CMS field values, safe on the server too. Custom apps framed inside uidu also get `useUiduApp`, covered in [Custom apps](https://developers.uidu.org/docs/paths/custom-app.md). The [`@uidu/react` reference](https://developers.uidu.org/docs/reference/react.md) lists every export.

In Server Components you don't need any of these: `await` a `@uidu/client` function directly.

## `useQuery(document, variables?, options?)`

Run any generated `@uidu/client` document from a Client Component. It uses SWR over the client from the nearest [`UiduProvider`](https://developers.uidu.org/docs/tools/react/getting-started.md#provider): results are cached and deduplicated by operation name + variables, and revalidate on focus by default.

```tsx
'use client';
import { useQuery } from '@uidu/react';
import { ListEventsDocument } from '@uidu/client';

export function UpcomingEvents() {
  const { data, error, isLoading } = useQuery(ListEventsDocument, { first: 10 });

  if (isLoading) return <p>Loading…</p>;
  if (error) return <p>Couldn't load events.</p>;

  const events = data?.currentWorkspace?.events?.edges?.map((e) => e?.node) ?? [];
  return <ul>{events.map((ev) => ev && <li key={ev.id}>{ev.name}</li>)}</ul>;
}
```

|               |                                                                                                                                                                         |
| ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Arguments** | `document` — any `*Document` exported by `@uidu/client`; `variables` — its typed variables; `options` — `revalidateOnFocus`, `revalidateOnReconnect`, `refreshInterval` |
| **Returns**   | `{ data, error, isLoading, mutate }` — `data` is the raw query result (the GraphQL shape, not the flattened array a `list*` function returns)                           |
| **Runtime**   | Client only — requires `UiduProvider`                                                                                                                                   |

<Callout type="info" title="Raw shape">
  `useQuery` returns what the query returns, so connections come as `edges[].node`. The `list*` functions in `@uidu/client` flatten that for you; with `useQuery` you do it yourself, as above.
</Callout>

There are no per-domain hooks (`useEvents`, `usePage`…) yet: `useQuery` plus a generated document covers the same ground.

## `useUiduClient()`

Read the client instance from any Client Component descendant of [`UiduProvider`](https://developers.uidu.org/docs/tools/react/getting-started.md#provider).

```tsx
'use client';
import { useUiduClient } from '@uidu/react';
import { search } from '@uidu/client';

export function SearchButton({ q }: { q: string }) {
  const client = useUiduClient();

  async function run() {
    // any @uidu/client function works with this client
    const results = await search(client, {
      params: { filters: [{ field: 'name', op: 'matches', value: q }] },
    });
    console.log(results);
  }

  return <button onClick={run}>Search</button>;
}
```

|             |                                                                     |
| ----------- | ------------------------------------------------------------------- |
| **Returns** | `UiduClient` instance                                               |
| **Throws**  | `Error` with a descriptive message if called outside `UiduProvider` |
| **Runtime** | Client only — requires React context                                |

<Callout type="warn" title="Server Components">
  Don't call `useUiduClient()` from a Server Component. Server Components should import the server-side client directly from `lib/uidu.ts` (the one with the API key).
</Callout>

## `useUidu()`

Lower-level accessor — returns the full provider context: the client plus the resolved endpoint URL. Rarely needed in app code; prefer `useUiduClient()` unless you specifically need the endpoint.

```tsx
'use client';
import { useUidu } from '@uidu/react';

export function DebugInfo() {
  const { client, endpoint } = useUidu();
  return <code>{endpoint}</code>;
}
```

|             |                                            |
| ----------- | ------------------------------------------ |
| **Returns** | `{ client: UiduClient, endpoint: string }` |
| **Throws**  | `Error` if called outside `UiduProvider`   |

## `useFields(fieldValues)`

Normalize a `fieldValues` array (from a CMS page block) into a `{ shortname: value }` map. **Pure function** — safe to call from Server Components, Client Components, or anywhere else. The `use` prefix is a naming convention only; no React state or effects are involved.

```tsx
import type { Page } from '@uidu/client';
import { useFields, toText } from '@uidu/react';

type PageBlock = NonNullable<Page['pageBlocks']>[number];

export function Hero({ block }: { block: PageBlock }) {
  const fields = useFields(block.fieldValues);
  return (
    <header>
      <h1>{toText(fields.Titolo)}</h1>
      <p>{toText(fields.Sottotitolo)}</p>
    </header>
  );
}
```

### Three kinds of values

`useFields` handles the three shapes a uidu field value can take:

| Field `kind`                         | Output                                                                         |
| ------------------------------------ | ------------------------------------------------------------------------------ |
| Scalar (text, number, boolean, etc.) | `fieldValue.content.value` — the raw value                                     |
| Collection                           | `fieldValue.content` — the whole content object (typically `{ items: [...] }`) |
| Linked record                        | `fieldValue.linkedRecord` — the embedded record (e.g. a Form, a Contact)       |

Field values without a `shortname` are dropped.

|             |                                 |
| ----------- | ------------------------------- |
| **Returns** | `Record<string, unknown>`       |
| **Pure**    | Yes — no React state or effects |
| **Runtime** | Anywhere                        |

## `toText(value)` (utility)

Flatten any field value to a plain string. Handles raw strings, numbers, arrays of nodes, and Slate-style rich text trees (`{ type, children }`, `{ text }`). Used in tandem with `useFields` to handle the case where the CMS stores a "title" field as either a plain string **or** a rich-text fragment.

```tsx
toText('hello');                                          // → 'hello'
toText(42);                                               // → '42'
toText({ type: 'paragraph', children: [{ text: 'hi' }] }); // → 'hi'
toText([{ text: 'a ' }, { text: 'b', bold: true }]);      // → 'a b'
toText(null);                                             // → ''
```

For genuine rich text (not just a single string), use [`<RichText>`](https://developers.uidu.org/docs/tools/react/components.md#richtext-doc-) — it renders the same tree as React elements with proper marks, lists, headings, and so on.

|             |                                                                |
| ----------- | -------------------------------------------------------------- |
| **Returns** | `string` (empty string when value is null/undefined/unhandled) |
| **Pure**    | Yes                                                            |
| **Runtime** | Anywhere                                                       |
