Initialization, readiness, resets, and transaction ownership across every Sheetwrite framework adapter.On this page
Loading documentation…
Every adapter follows one lifecycle:
mount the framework component;
initialize the shared WASM runtime;
create one Grid generation;
publish readiness;
reset only when structural ownership changes;
destroy the generation on unmount.
Pick a framework in any tab group below; the selection is remembered and reused across documentation pages.
Pick the ownership model
Use Sheetwrite for a data-first, uncontrolled grid: pass columns plus initial rows and let the component own the live document.
Use SheetwriteGrid for an advanced Workbook plus eager data or a datasource. It exposes the imperative Grid after readiness and keeps structural configuration under the host's control.
The imperative core has one ownership mode: the host supplies the workbook and data, awaits runtime initialization, and destroys the returned grid.
defaultRows is seed data. Changing it after mount does not replace committed edits; a new columns, defaultRows, or sheetName identity derives a new document and creates a new generation.
The template ref exposes { grid } after readiness. defaultRows seeds the document once; a new columns, defaultRows, or sheetName identity creates a new generation.
bind:grid publishes the live handle and clears it on reset or unmount. defaultRows seeds the document once; a new columns, defaultRows, or sheetName identity creates a new generation.
Readiness is generation-scoped
onReady receives { grid, generation, reason }. generation is one-based and increments whenever the adapter replaces its Grid. reason is exactly one of:
"initial" — the first generation after mount and WASM initialization;
"input-reset" — a reset-classified document input changed identity;
"renderer-reset" — renderer, workerUrl, or renderers changed identity.
The exposed handle (React ref, Vue expose, Svelte bind:grid) is assigned before onReady runs and cleared when that generation is destroyed. Reattach subscriptions and collaboration coordinators inside onReady; never retain a stale Grid across a reset.
Controlled values do not reset the document
theme, readOnly, config, overscan, and minColumns are live: changing them updates the current generation in place without recreating the grid or replaying defaultRows. Callbacks and host sizing (height, fill, className/class, style) are also safe to change live.
Structural changes are different. Every reset-classified input is compared by identity:
Keep reset-classified inputs referentially stable (module constants, memoized values, or state) unless you intend to create a new generation.
Transactions and persistence
onGridChange receives committed transactions. transaction.patches is the exhaustive document operation list; changes is the cell-level compatibility view.
Use event.reason for audit context, not to reconstruct the transaction. For offline durability and replay, persist operations with SheetwriteStore or your own PersistenceAdapter.
Initialization failures
Framework components surface initialization errors instead of rendering a dead grid. React uses fallback and onInitializationError; Vue and Svelte support fallback content or slots plus their error callback/event.
WASM initialization is process-wide and monotonic: every adapter converges on the same runtime, and when several pass an explicit wasmSource concurrently, the first source wins. While initialization has not yet succeeded, a changed wasmSource or a remount retries it; after the runtime is ready, the source is fixed for the process.
Server rendering
Importing an adapter during SSR is safe, but the grid initializes only after a browser mount. Put it behind the host framework's client boundary:
React/Next.js: a client component;
Nuxt: <ClientOnly>;
SvelteKit: a browser-only branch or client-mounted component.
No framework owns the global runtime. All adapters converge on the same monotonic initializer.
function createGrid(host: HTMLElement, opts: GridOptions): GridfunctioncreateGrid(host:HTMLElement,opts:GridOptions,):GridfunctioncreateGrid(host:HTMLElement,opts:GridOptions,):GridCreates and mounts an imperative Grid in the supplied host element.@example import { createGrid, initSheetwrite } from "@sheetwrite/core"; await initSheetwrite(); const host = document.createElement("div"); host.style.height = "400px"; document.body.append(host); const grid = createGrid(host, { workbook: { activeSheet: "sales", sheets: [{ id: "sales", name: "Sales", rowCount: 2, columns: [{ key: "amount", header: "Amount", type: "number", width: 120 }] }], }, data: { rowCount: 2, columns: { amount: [12, 18] } }, }); grid.scrollToCell({ sheet: "sales", row: 1, col: 0 }); // Call when the host view is removed. grid.destroy();@see Grid *@see GridOptionsAPI reference →function initSheetwrite(source?: BufferSource | URL | string | Request | WebAssembly.Module, engine?: SheetwriteEngine): Promise<void>functioninitSheetwrite(source?:BufferSource|URL|string|Request|WebAssembly.Module,engine?:SheetwriteEngine,):Promise<void>functioninitSheetwrite(source?:|BufferSource|URL|string|Request|WebAssembly.Module,engine?:SheetwriteEngine,):Promise<void>Load one WASM engine before createGrid. The default is @sheetwrite/wasm. Pass the @sheetwrite/formulas module as the second argument to select the full engine.@example import { initSheetwrite } from "@sheetwrite/core"; import * as formulas from "@sheetwrite/formulas"; await initSheetwrite(undefined, formulas);@see /docs/guides/formulas/@see createGridAPI reference →const grid: Gridconstgrid:Gridconstgrid:GridThe imperative core grid this controller owns.API reference →const host: HTMLElementconsthost:HTMLElementconsthost:HTMLElementGridOptions.workbook: WorkbookinterfaceGridOptions {workbook:Workbook;}interfaceGridOptions {workbook:Workbook;}Live workbook schema adopted by the store and updated by document operations.API reference →GridOptions.data?: ColumnarData | undefinedinterfaceGridOptions {data?:ColumnarData|undefined;}interfaceGridOptions {data?:ColumnarData|undefined;}Eager column-major values loaded into workbook.activeSheet; use instead of datasource.API reference →Grid.destroy(): voidGrid.destroy(): voidGrid.destroy(): voidRuns immediately before a retained element is removed or replaced.API reference →const Sheetwrite: <Row extends Record<string, CellScalar>, Id extends RowBridgeId = RowBridgeId>(props: SheetwriteProps<Row, Id> & {
ref?: ForwardedRef<Grid>;
}) => ReactElementconstSheetwrite: <RowextendsRecord<string, CellScalar>,IdextendsRowBridgeId=RowBridgeId,>(props:SheetwriteProps<Row, Id> & {ref?:ForwardedRef<Grid>;},) =>ReactElementconstSheetwrite: <RowextendsRecord<string,CellScalar>,IdextendsRowBridgeId=RowBridgeId,>(props:SheetwriteProps<Row,Id> & {ref?:ForwardedRef<Grid>;},) =>ReactElementConvenience component for local object rows. It derives a single-sheet workbook from columns, defaultRows, and sheetName, initializes Sheetwrite, and owns the Grid through prop-driven resets and unmount cleanup. Pass a ref to access the live Grid; use SheetwriteGrid when the host already owns a workbook or datasource.@example import { Sheetwrite } from "@sheetwrite/react"; export function Sales() { return <Sheetwrite columns={[{ key: "amount", title: "Amount", type: "number" }]} defaultRows={[{ amount: 12 }, { amount: 18 }]} height={400} />; }@see SheetwriteGrid *@see /docs/frameworks/react/API reference →columns: readonly SimpleColumn<Record<string, CellScalar>>[]let columns:readonlySimpleColumn<Record<string, CellScalar>>[]let columns:readonlySimpleColumn<Record<string, CellScalar>>[]Ordered schema used to derive the component-owned sheet.API reference →const columns: readonly SimpleColumn<Record<string, CellScalar>>[]constcolumns:readonlySimpleColumn<Record<string, CellScalar>>[]constcolumns:readonlySimpleColumn<Record<string, CellScalar>>[]Exact column runs represented by every returned row.API reference →defaultRows: readonly Record<string, CellScalar>[]let defaultRows:readonlyRecord<string, CellScalar>[]let defaultRows:readonlyRecord<string,CellScalar>[]Rows converted to initial columnar data; missing column keys become null.API reference →const rows: readonly Record<string, CellScalar>[]constrows:readonlyRecord<string, CellScalar>[]constrows:readonlyRecord<string,CellScalar>[]end-exclusive row rangeAPI reference →onGridChange?: ((event: ChangeEvent) => void) | undefinedonGridChange?: ((event:ChangeEvent) =>void) |undefinedonGridChange?: ((event:ChangeEvent) =>void) |undefinedReceives every committed Grid change, including its applied transaction.API reference →const persist: (transaction: Transaction) => voidconstpersist: (transaction:Transaction) =>voidconstpersist: (transaction:Transaction,) =>voidAPI reference →onReady?: ((event: GridReadyEvent) => void) | undefinedonReady?: ((event:GridReadyEvent) =>void) |undefinedonReady?: ((event:GridReadyEvent) =>void) |undefinedFires after the adapter publishes a ready Grid generation.API reference →grid: Gridlet grid:Gridlet grid:GridLive handle just published by the adapter; replaced on the next reset generation.API reference →generation: numberlet generation:numberlet generation:numberOne-based adapter generation, incremented whenever a Grid is replaced.API reference →reason: GridReadyReasonlet reason:GridReadyReasonlet reason:GridReadyReasonWhether readiness followed first initialization, an input reset, or a renderer reset.API reference →const observe: (grid: Grid, generation: number, reason: string) => voidconstobserve: (grid:Grid,generation:number,reason:string,) =>voidconstobserve: (grid:Grid,generation:number,reason:string,) =>voidAPI reference →const SheetwriteGrid: <Id extends RowBridgeId = RowBridgeId>(props: SheetwriteGridProps<Id> & {
ref?: ForwardedRef<Grid>;
}) => ReactElementconstSheetwriteGrid: <IdextendsRowBridgeId=RowBridgeId,>(props:SheetwriteGridProps<Id> & {ref?:ForwardedRef<Grid>;},) =>ReactElementconstSheetwriteGrid: <IdextendsRowBridgeId=RowBridgeId,>(props:SheetwriteGridProps<Id> & {ref?:ForwardedRef<Grid>;},) =>ReactElementAdvanced framework component with inferred row-bridge identity.@example import { SheetwriteGrid } from "@sheetwrite/react"; import type { Workbook } from "@sheetwrite/core"; export function WorkbookView({ workbook }: { workbook: Workbook }) { return <SheetwriteGrid workbook={workbook} height={400} />; }@see Sheetwrite *@see /docs/frameworks/react/API reference →ref?: ForwardedRef<Grid> | undefinedref?: ForwardedRef<Grid>|undefinedref?: ForwardedRef<Grid>|undefinedAPI reference →const gridRef: Grid | nullconstgridRef:Grid|nullconstgridRef:Grid|nullAPI reference →const workbook: Workbookconstworkbook:Workbookconstworkbook:WorkbookLive workbook schema adopted by the store and updated by document operations.API reference →GridOptions.datasource?: DataSource | undefinedinterfaceGridOptions {datasource?:DataSource|undefined;}interfaceGridOptions {datasource?:DataSource|undefined;}Lazy row provider requested for visible windows; use instead of eager data.API reference →const datasource: DataSourceconstdatasource:DataSourceconstdatasource:DataSourceLazy row provider requested for visible windows; use instead of eager data.API reference →SheetwriteGridProps<RowBridgeId>.onReady?: ((event: GridReadyEvent) => void) | undefinedinterfaceSheetwriteGridProps<RowBridgeId> {onReady?: ((event:GridReadyEvent) =>void) |undefined;}interfaceSheetwriteGridProps<RowBridgeId,> {onReady?:| ((event:GridReadyEvent,) =>void)|undefined;}Fires after the adapter publishes a ready Grid generation.API reference →const connect: (grid: Grid) => voidconstconnect: (grid:Grid) =>voidconstconnect: (grid:Grid,) =>voidAPI reference →interface GridReadyEventinterfaceGridReadyEventinterfaceGridReadyEventGrid handle, generation, and reason published after adapter initialization.API reference →const handleReady: ({ grid, generation, reason }: GridReadyEvent) => voidconsthandleReady: ({grid,generation,reason,}:GridReadyEvent) =>voidconsthandleReady: ({grid,generation,reason,}:GridReadyEvent) =>voidAPI reference →const Sheetwrite: Component<SheetwriteProps<Record<string, CellScalar>>, {}, "grid">constSheetwrite:Component<SheetwriteProps<Record<string, CellScalar>>,{},"grid">constSheetwrite:Component<SheetwriteProps<Record<string, CellScalar>>,{},"grid">Owns a sheet derived from columns and defaultRows. Bind grid for imperative access; it clears on reset or unmount.API reference →columns: readonly SimpleColumn<Record<string, CellScalar>>[]let columns:readonlySimpleColumn<Record<string, CellScalar>>[]let columns:readonlySimpleColumn<Record<string, CellScalar>>[]Exact column runs represented by every returned row.API reference →interface GridinterfaceGridinterfaceGridImperative grid handle for document commands, events, rendering, and teardown.@example import type { Grid } from "@sheetwrite/core"; function updateTotal(grid: Grid) { const sheet = grid.getActiveSheet(); const result = grid.applyTransaction({ patches: [{ op: "set", addr: { sheet, row: 0, col: 0 }, value: { kind: "literal", value: 42 } }], }); if (result.status === "applied") grid.scrollToCell({ sheet, row: 0, col: 0 }); return grid.aggregate(0, "sum"); }@see createGrid *@see Grid.applyTransactionAPI reference →const handleReady: ({ grid }: GridReadyEvent) => voidconsthandleReady: ({ grid }:GridReadyEvent) =>voidconsthandleReady: ({grid,}:GridReadyEvent) =>voidAPI reference →const SheetwriteGrid: Component<SheetwriteGridProps<RowBridgeId>, {}, "grid">constSheetwriteGrid:Component<SheetwriteGridProps<RowBridgeId>,{},"grid">constSheetwriteGrid:Component<SheetwriteGridProps<RowBridgeId>,{},"grid">Advanced framework component for workbook data or datasource input.API reference →grid: Grid | nulllet grid:Grid|nulllet grid:Grid|nullLive handle just published by the adapter; replaced on the next reset generation.API reference →workbook: Workbooklet workbook:Workbooklet workbook:WorkbookLive workbook schema adopted by the store and updated by document operations.API reference →datasource: DataSourcelet datasource:DataSourcelet datasource:DataSourceLazy row provider requested for visible windows; use instead of eager data.API reference →interface ChangeEventinterfaceChangeEventinterfaceChangeEventPayload of the change event; flows OUT for API submission/reconcile.API reference →event: ChangeEventlet event:ChangeEventlet event:ChangeEventAPI reference →ChangeEvent.source: OperationSourceinterfaceChangeEvent {source:OperationSource;}interfaceChangeEvent {source:OperationSource;}Remote input is observable but never belongs in outgoing local persistence.API reference →const operationQueue: {
push(...patches: Transaction["patches"]): void;
}constoperationQueue: {push(...patches:Transaction["patches"]):void;}constoperationQueue: {push(...patches:Transaction["patches"]):void;}API reference →function push(...patches: Transaction["patches"]): voidfunctionpush(...patches:Transaction["patches"]):voidfunctionpush(...patches:Transaction["patches"]):voidAPI reference →ChangeEvent.transaction: TransactioninterfaceChangeEvent {transaction:Transaction;}interfaceChangeEvent {transaction:Transaction;}Operations that actually committed after policy and bounds filtering.API reference →Transaction.patches: DocumentOp[]interfaceTransaction {patches:DocumentOp[];}interfaceTransaction {patches:DocumentOp[];}Ordered document operations submitted as one store commit.API reference →