useRecord

One live record from a "get" query, normalized — the headless core of RecordView.

A detail view wants one record, but a "get" query may return a row array or a single object depending on how it was written. useRecord subscribes and normalizes that away, so the component never branches on the shape.

import { useRecord } from '@voltro/client'

const { record, loading, error } = useRecord('app', 'users.get', { id })

An array result yields its first row; an object result is the record itself; anything else is undefined. loading is true exactly while no snapshot has arrived, and error is the underlying subscription's cold-start error.

It is a thin projection over useSubscription — same live semantics, so the detail view updates on any write with no refetch — with the single difference that it takes no options argument, only (apiName, queryTag, input?). Eager loaded relations arrive as nested arrays on the record.

Reach for it when you want the data but not the markup. <RecordView> is this hook plus a rendered definition list and sub-tables.