uidudevelopers
ToolsReact

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. The @uidu/react reference 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: results are cached and deduplicated by operation name + variables, and revalidate on focus by default.

'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>;
}
Argumentsdocument — 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)
RuntimeClient only — requires UiduProvider

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.

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.

'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>;
}
ReturnsUiduClient instance
ThrowsError with a descriptive message if called outside UiduProvider
RuntimeClient only — requires React context

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).

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.

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

export function DebugInfo() {
  const { client, endpoint } = useUidu();
  return <code>{endpoint}</code>;
}
Returns{ client: UiduClient, endpoint: string }
ThrowsError 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.

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 kindOutput
Scalar (text, number, boolean, etc.)fieldValue.content.value — the raw value
CollectionfieldValue.content — the whole content object (typically { items: [...] })
Linked recordfieldValue.linkedRecord — the embedded record (e.g. a Form, a Contact)

Field values without a shortname are dropped.

ReturnsRecord<string, unknown>
PureYes — no React state or effects
RuntimeAnywhere

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.

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> — it renders the same tree as React elements with proper marks, lists, headings, and so on.

Returnsstring (empty string when value is null/undefined/unhandled)
PureYes
RuntimeAnywhere

On this page