useGrist The primary hook. Returns a single object with every commonly-needed Grist capability.
The primary hook. Returns a single object with every commonly-needed Grist capability.
function useGrist < TRow = GristRecordFields , TMapped = TRow >(
options ?: UseGristOptions ,
) : UseGristResult < TRow , TMapped >
Behavior:
Inside <GristWidgetProvider>, useGrist() returns the shared context slices — no extra work, no duplicate subscriptions. options are ignored (the provider owns the configuration).
Outside <GristWidgetProvider>, useGrist() mounts its own private subscriptions (single-leaf widget mode) using the options argument. Prefer the provider in app code.
The slice hooks (useGristStatus, useGristSelection, useGristWrites, useGristTheme) are provider-only and throw when called outside <GristWidgetProvider>.
A superset of GristReadyOptions (see <GristWidgetProvider> ):
type UseGristOptions = GristReadyOptions & {
// No additional fields today. Reserved for future hook-only knobs.
}
Every field is annotated with its minimum access level. Set requiredAccess on
your UseGristOptions / <GristWidgetProvider> accordingly — calling a method
that needs "full" when you declared "read table" will fail at runtime.
Available without any document access. Useful for connection status and theming.
Field Type Notes status"booting" | "unavailable" | "ready" | "error"Connection state. isAvailableboolean | nulltrue if the page is in a Grist iframe.isReadybooleanConvenience for status === "ready". errorstring | nullConnection-level error string. reload() => Promise<void>Re-run the handshake. capabilitiesGristCapabilitiesHandshake-derived gates — see below. theme"light" | "dark" | nullResolved Grist theme.
capabilities is projected from the same snapshot as useGristHandshake() . Use it for UI gates without importing /advanced.
Field Meaning canReadOnline, link ok, read access granted. canRendercanRead and mappings usable (complete or not_declared).canWriteRecordscanRender + full document access.canWriteSchemacanWriteRecords + current table id known.canFetchTablecanRead + link connected.hasFreshSelectionHot record stream + mappings ok. hasUsableMappingsMapping state is complete or not declared. missingMappingsLogical column names still unmapped. emptyMultipleMappingsallowMultiple columns mapped to [].
Pair with <GristBoundary gate="canRender"> when the widget requires declared columns.
Requires at least Read selected table access.
Field Type Notes recordGristRowRecord<TRow> | nullCurrently selected row (raw column ids). recordsGristRowRecord<TRow>[] | nullAll visible rows in the section. mappedRecordTMapped | nullSelected row under logical names. null if required mappings missing. mappingsRecord<string, string | string[]>logical → real for the single-record stream. recordsMappingsRecord<string, string | string[]>logical → real for the multi-record stream. newRecordMappingsRecord<string, string | string[]>logical → real for the new-row placeholder. mode"empty" | "row" | "new-row"Derived from selection state. isNewRecordbooleanmode === "new-row".columnMappingStatus{ ok: boolean; missing: string[]; emptyMultiples: string[] }Required-column gating. widgetInteractionRecord<string, unknown> | nullSecond arg of onOptions, includes access_level. mapBack(patch)(patch: Partial<TMapped>) => Record<string, unknown>Reverse-map a logical patch. mapBackSkippedreadonly string[]Logical names that the last mapBack could not reverse-map (e.g. allowMultiple columns). Powers the map-back-skip alert descriptor. resolveMappedColumnId(name)(name: string) => stringOne-shot column resolution (returns name as a fallback).
Field Type Notes currentTableIdstring | nullCurrent section's table id. currentTableLoadingbooleanTrue while the SDK re-reads selectedTable.getTableId(). refreshCurrentTable() => Promise<void>Force a re-read.
Field Type Notes fetchSelectedTable(opts?)row-shaped read of the current section fetchSelectedRecord<T>(rowId, opts?)row of the current section listTables(options?)(opts?: ListTablesOptions) => Promise<string[]>System/hidden tables filtered by default. getDocName()() => Promise<string>readErrorstring | nullLast access-insufficient read error. Drives the access-insufficient SDK alert.
Field Type widgetOptionsRecord<string, unknown> | nullgetWidgetOptions()Promise<Record<string, unknown>>getWidgetOption(key)Promise<unknown>
Field Type setCursorPosition(pos)(pos: GristCursorPos) => Promise<void>setLinkedRowSelection(ids | null)(rows: number[] | null) => Promise<void>
Field Type configure(options)(GristReadyOptions) => Promise<void>refreshMappings()Promise<Record<string, string | string[]>>
Requires Full document access . Calling these methods with requiredAccess: "read table" will fail at runtime. The SDK guards them with a pre-flight access check — no RPC is made — and surfaces an access-insufficient alert with actionable instructions via readError / actionError.
Field Type Notes fetchTable<T>(tableId)(id) => Promise<Record<string, unknown[]>>Raw columnar payload for any table. fetchTableRows<T>(id, opts?)row-shaped, decoded, optionally safe-parsed See Reading data . fetchRow<T>(id, rowId)row by id from any table listColumns(tableId, options?)(id, opts?) => Promise<GristColumnInfo[]>Column metadata without fetching rows. buildReplicaDocumentFromDocApi(opts?)(opts) => Promise<GristReplicaDocument>Bound version of the helper.
Field Type Notes tableGristTableOperationsCRUD on the current table (create, update, upsert, destroy). getTable(id)(id: string) => GristTableOperationsMemoized CRUD for any table. actionStatus"idle" | "running" | "error"Last write status. actionErrorstring | nullLast write error message.
Field Type Notes applyActions(actions: GristActionTuple[], options?: { desc?: string }) => Promise<unknown>Apply user-action tuples atomically.
Field Type setWidgetOption(key, value)Promise<void>setWidgetOptions(next)Promise<void>patchWidgetOptions(patch)Promise<void>clearWidgetOptions()Promise<void>
Field Type getAttachmentUrl(id, opts?)Promise<string>fetchAttachmentBlob(id, opts?)Promise<{ blob: Blob; contentType: string }>fetchAttachmentBase64(id, opts?)Promise<{ base64: string; contentType: string }>getAccessToken(opts?)Promise<{ token: string; baseUrl: string }>fetchWithAuth(path, init?)(path, init?) => Promise<Response>uploadAttachment(file, opts?)Promise<{ ids: string[]; firstId: string }>
opts.readOnly is supported on download/token/fetch helpers. uploadAttachment always uses a write token. The path for fetchWithAuth is relative to the document API root (baseUrl from getAccessToken).
function Toggle () {
const w = useGrist <{ Done : boolean }, { Done : boolean }>()
if (w.mode !== "row" ) return null
return (
< button
disabled = {w.actionStatus === "running" }
onClick = {() =>
w.table. update ({
id: w.record ! .id,
fields: w. mapBack ({ Done: ! w.mappedRecord ! .Done }),
})
}
>
{w.mappedRecord ! .Done ? "Mark not done" : "Mark done" }
</ button >
)
}
function StatusLine () {
const { status , error , reload } = useGrist ()
if (status === "ready" ) return null
if (status === "error" ) return (
< p >Error: {error} < button onClick = {reload}>Retry</ button ></ p >
)
if (status === "unavailable" ) return < p >Open this widget inside a Grist document.</ p >
return < p >Connecting…</ p >
}
async function migrate ( w : ReturnType < typeof useGrist>) {
await w. applyActions (
[
gristAddColumnAction ( "Tasks" , "Priority" , { type: "Choice" }),
gristRenameColumnAction ( "Tasks" , "Title" , "Name" ),
],
{ desc: "Add Priority column" },
)
}
const r = await w. fetchWithAuth ( "/api/docs/.../sql" , {
method: "POST" ,
body: JSON . stringify ({ sql: "SELECT id, Name FROM Tasks LIMIT 5" }),
})
const data = await r. json ()