Records
Runtime instances of objects: how to fetch, create, update, and delete them with React hooks.
Records are the runtime instances of objects. The React hooks in @stndrds/react load and mutate them.
// @noverify
import { useCreateRecord, useRecords } from "@stndrds/react";
function ContactList() {
const { data: contacts, isLoading } = useRecords("contacts");
const create = useCreateRecord("contacts");
if (isLoading) return null;
return (
<ul>
{contacts?.data.map((c) => (
<li key={c.id}>{c.values.firstName}</li>
))}
</ul>
);
}useRecords takes the object name as a positional string argument, not a config object. The response is { data: TypedRecord[], total: number }.
Hook surface
| Hook | Use case |
|---|---|
useRecord | fetch one record by id |
useRecords | fetch a list |
useSearchRecords | text search |
useInfiniteSearchRecords | paginated search |
useCreateRecord | create |
useUpdateRecord | update |
useDeleteRecord | delete single (soft — moves to archive) |
useRestoreRecord | restore a soft-deleted record |
usePurgeRecord | permanently destroy a soft-deleted record |
useBulkDeleteRecords | bulk delete |
useObject / useObjects | fetch object definitions |
useMyProfile | current actor |
useSchemaClient | direct client access (escape hatch) |
Query keys
Always use the recordsKeys factory from @stndrds/react when interacting with the query cache. Never write ad-hoc key arrays — the factory guarantees that invalidations cover all cache shapes (list, detail, grid, kanban).
// @noverify
import { recordsKeys } from "@stndrds/react";
import { useQueryClient } from "@tanstack/react-query";
const queryClient = useQueryClient();
queryClient.invalidateQueries({
queryKey: recordsKeys.list("contacts"),
});Available keys: all, lists, list, details, detail, grids, grid, kanbans, kanban, search, searchInfinite.
Optimistic updates
Optimistic update logic lives in @stndrds/react hooks (useUpdateRecord.onMutate). The pattern snapshots all relevant caches, applies the update immediately, and rolls back on error. Do not replicate this logic in @stndrds/ui components.
Optimistic updates belong in @stndrds/react, never in @stndrds/ui. The useRecordSave hook in @stndrds/ui is a thin wrapper — it does not touch the query cache.
Deletion is now a soft-delete: useDeleteRecord archives the record (sets deletedAt) and cascade-archives its edges. Restore via useRestoreRecord — only cascade-tagged edges wake up; edges independently archived stay archived. To permanently destroy a record, soft-delete it first, then call usePurgeRecord (requires manage permission).