Skip to content

Advanced hooks

Lower-level hooks for use cases the default surface doesn't cover. Import from the /advanced subpath.

ts
import {
  useGristReady,
  useGristAvailability,
  useGristRowsFromTable,
  useGristWidgetOptions,
} from "grist-widget-sdk/advanced"

useGristReady(options?)

Runs the grist.ready handshake manually. Useful when you don't want <GristWidgetProvider> — e.g. in a tiny library that just needs docApi.

ts
const { docApi, error, reload } = useGristReady({ requiredAccess: "read table" })

useEffect(() => {
  if (!docApi) return
  void docApi.listTables().then(setTables)
}, [docApi])

Returns:

ts
type UseGristReadyResult = {
  docApi: GristDocApi | null
  error: string | null
  reload: () => Promise<void>
}

Concurrent useGristReady calls coalesce a single grist.ready invocation, but you should still aim for one call per app.

useGristAvailability(options?)

Polls for the global grist object until it appears or maxAttempts is reached.

ts
const isAvailable = useGristAvailability({
  maxAttempts: 30,
  intervalMs: 200,
  logWhenNotEmbedded: false,
})

Returns boolean. SSR-safe (returns false outside the browser).

Use this when writing a custom <GristBoundary> replacement.

useGristRowsFromTable<T>(options)

Polls a non-section table for changes.

ts
const { rows, refresh, loading, error } = useGristRowsFromTable<MyRow>({
  tableId: "Reports",
  pollIntervalMs: 10_000,
  filter: (row) => row.Status === "open",
  order: "grist",
  columns: schema.columns,        // for decoding
  safeParse: true,                // optional
})

The hook:

  • Reads the table on mount and at every interval.
  • Skips empty intervals when the tab is hidden.
  • Always returns a stable array reference until the underlying data changes.

useGristWidgetOptions<T>(options?)

Typed widget options with debounced writes.

ts
const { options, patchOptions, setOptions, reset, loading, error } =
  useGristWidgetOptions<MySettings>({
    defaults: { theme: "light", autoRefresh: false },
    debounceMs: 200,
    namespace: "ui",  // optional: writes to grist.setOption("ui", value) only
  })

Returns:

ts
type UseGristWidgetOptionsResult<T> = {
  options: T
  patchOptions: (patch: Partial<T>) => void
  setOptions: (next: T) => void
  reset: () => void
  loading: boolean
  error: string | null
}

The debounced writer collapses bursts of patchOptions(...) into one Grist call.

When to escape to plain plugin API

If you've truly outgrown the SDK, useGrist() exposes docApi and you can call any grist.* method directly. Don't try to recreate the subscription / write paths the SDK already runs — wire your custom call in as a sibling, not a replacement.

Released under the ISC License.