Initialization, readiness, resets, and transaction ownership across every Sheetwrite framework adapter.
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.
Vanilla lifecycle
import { createGridfunction 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.API reference →, initSheetwritefunction initSheetwrite(source?: BufferSource | URL | string | Request | WebAssembly.Module): Promise<void>functioninitSheetwrite(source?:BufferSource|URL|string|Request|WebAssembly.Module,):Promise<void>functioninitSheetwrite(source?:|BufferSource|URL|string|Request|WebAssembly.Module,):Promise<void>Load the WASM data engine once. Must be awaited before createGrid.API reference → } from"@sheetwrite/core";
awaitinitSheetwritefunction initSheetwrite(source?: BufferSource | URL | string | Request | WebAssembly.Module): Promise<void>functioninitSheetwrite(source?:BufferSource|URL|string|Request|WebAssembly.Module,):Promise<void>functioninitSheetwrite(source?:|BufferSource|URL|string|Request|WebAssembly.Module,):Promise<void>Load the WASM data engine once. Must be awaited before createGrid.API reference →();
constgridconst grid: Gridconstgrid:Gridconstgrid:GridThe imperative core grid this controller owns.API reference →=createGridfunction 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.API reference →(hostconst host: HTMLElementconsthost:HTMLElementconsthost:HTMLElement, { workbookGridOptions.workbook: WorkbookinterfaceGridOptions {workbook:Workbook;}interfaceGridOptions {workbook:Workbook;}Live workbook schema adopted by the store and updated by document operations.API reference →, dataGridOptions.data?: ColumnarData | undefinedinterfaceGridOptions {data?:ColumnarData|undefined;}interfaceGridOptions {data?:ColumnarData|undefined;}Eager column-major values loaded into workbook.activeSheet; use instead of datasource.API reference → });
// Later, when the host DOM lifetime ends:
gridconst grid: Gridconstgrid:Gridconstgrid:GridThe imperative core grid this controller owns.API reference →.destroyGrid.destroy(): voidGrid.destroy(): voidGrid.destroy(): voidDetach every event subscription and destroy the grid. Call exactly once.API reference →();
React ownership
<Sheetwriteconst Sheetwrite: <Row extends Record<string, CellScalar>>(props: SheetwriteProps<Row> & {
ref?: ForwardedRef<Grid>;
}) => ReactElementconstSheetwrite: <RowextendsRecord<string, CellScalar>>(props:SheetwriteProps<Row> & {ref?:ForwardedRef<Grid>;},) =>ReactElementconstSheetwrite: <RowextendsRecord<string,CellScalar>,>(props:SheetwriteProps<Row> & {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.API reference →
columnscolumns: 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 →={columnsconst columns: readonly SimpleColumn<Record<string, CellScalar>>[]constcolumns:readonlySimpleColumn<Record<string, CellScalar>>[]constcolumns:readonlySimpleColumn<Record<string, CellScalar>>[]Restrict to these column indices (defaults to all columns).API reference →}
onReadyonReady?: ((event: GridReadyEvent) => void) | undefinedonReady?: ((event:GridReadyEvent) =>void) |undefinedonReady?: ((event:GridReadyEvent) =>void) |undefinedFires after the adapter publishes a ready Grid generation.API reference →={({ gridgrid: Gridlet grid:Gridlet grid:GridLive handle just published by the adapter; replaced on the next reset generation.API reference →, generationgeneration: numberlet generation:numberlet generation:numberOne-based adapter generation, incremented whenever a Grid is replaced.API reference →, reasonreason: GridReadyReasonlet reason:GridReadyReasonlet reason:GridReadyReasonWhether readiness followed first initialization, an input reset, or a renderer reset.API reference → }) =>observeconst observe: (grid: Grid, generation: number, reason: string) => voidconstobserve: (grid:Grid,generation:number,reason:string,) =>voidconstobserve: (grid:Grid,generation:number,reason:string,) =>void(gridgrid: Gridlet grid:Gridlet grid:GridLive handle just published by the adapter; replaced on the next reset generation.API reference →, generationgeneration: numberlet generation:numberlet generation:numberOne-based adapter generation, incremented whenever a Grid is replaced.API reference →, reasonreason: GridReadyReasonlet reason:GridReadyReasonlet reason:GridReadyReasonWhether readiness followed first initialization, an input reset, or a renderer reset.API reference →)}
/>
React advanced grid
<SheetwriteGridconst SheetwriteGrid: ForwardRefExoticComponent<SheetwriteGridProps & RefAttributes<Grid>>constSheetwriteGrid:ForwardRefExoticComponent<SheetwriteGridProps&RefAttributes<Grid>>constSheetwriteGrid:ForwardRefExoticComponent<SheetwriteGridProps&RefAttributes<Grid>>Advanced framework component for workbook data or datasource input.API reference →
refRefAttributes<Grid>.ref?: Ref<Grid> | undefinedinterfaceRefAttributes<Grid> {ref?:Ref<Grid> |undefined;}interfaceRefAttributes<Grid> {ref?:Ref<Grid> |undefined;}Allows getting a ref to the component instance. Once the component unmounts, React will set ref.current to null (or call the ref with null if you passed a callback ref).@see {@link react.dev/learn/referencing-values-with-refs#refs-and-the-dom React Docs}={gridRefconst gridRef: Grid | nullconstgridRef:Grid|nullconstgridRef:Grid|null}
workbookGridOptions.workbook: WorkbookinterfaceGridOptions {workbook:Workbook;}interfaceGridOptions {workbook:Workbook;}Live workbook schema adopted by the store and updated by document operations.API reference →={workbookconst workbook: Workbookconstworkbook:Workbookconstworkbook:WorkbookLive workbook schema adopted by the store and updated by document operations.API reference →}
datasourceGridOptions.datasource?: DataSource | undefinedinterfaceGridOptions {datasource?:DataSource|undefined;}interfaceGridOptions {datasource?:DataSource|undefined;}Lazy row provider requested for visible windows; use instead of eager data.API reference →={datasourceconst datasource: DataSourceconstdatasource:DataSourceconstdatasource:DataSourceLazy row provider requested for visible windows; use instead of eager data.API reference →}
onReadyGridAdapterEventHandlers.onReady?: ((event: GridReadyEvent) => void) | undefinedinterfaceGridAdapterEventHandlers {onReady?: ((event:GridReadyEvent) =>void) |undefined;}interfaceGridAdapterEventHandlers {onReady?:| ((event:GridReadyEvent,) =>void)|undefined;}Fires after the adapter publishes a ready Grid generation.API reference →={({ gridgrid: Gridlet grid:Gridlet grid:GridLive handle just published by the adapter; replaced on the next reset generation.API reference → }) =>connectconst connect: (grid: Grid) => voidconstconnect: (grid:Grid) =>voidconstconnect: (grid:Grid,) =>void(gridgrid: Gridlet grid:Gridlet grid:GridLive handle just published by the adapter; replaced on the next reset generation.API reference →)}
/>
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.
Svelte ownership
<scriptlang="ts">
importtype { GridReadyEventinterface GridReadyEventinterfaceGridReadyEventinterfaceGridReadyEventGrid handle, generation, and reason published after adapter initialization.API reference → } from"@sheetwrite/core/adapter";
consthandleReadyconst handleReady: ({ grid, generation, reason }: GridReadyEvent) => voidconsthandleReady: ({grid,generation,reason,}:GridReadyEvent) =>voidconsthandleReady: ({grid,generation,reason,}:GridReadyEvent) =>void= ({ gridgrid: Gridlet grid:Gridlet grid:GridLive handle just published by the adapter; replaced on the next reset generation.API reference →, generationgeneration: numberlet generation:numberlet generation:numberOne-based adapter generation, incremented whenever a Grid is replaced.API reference →, reasonreason: GridReadyReasonlet reason:GridReadyReasonlet reason:GridReadyReasonWhether readiness followed first initialization, an input reset, or a renderer reset.API reference → }:GridReadyEventinterface GridReadyEventinterfaceGridReadyEventinterfaceGridReadyEventGrid handle, generation, and reason published after adapter initialization.API reference →) =>
observeconst observe: (grid: Grid, generation: number, reason: string) => voidconstobserve: (grid:Grid,generation:number,reason:string,) =>voidconstobserve: (grid:Grid,generation:number,reason:string,) =>void(gridgrid: Gridlet grid:Gridlet grid:GridLive handle just published by the adapter; replaced on the next reset generation.API reference →, generationgeneration: numberlet generation:numberlet generation:numberOne-based adapter generation, incremented whenever a Grid is replaced.API reference →, reasonreason: GridReadyReasonlet reason:GridReadyReasonlet reason:GridReadyReasonWhether readiness followed first initialization, an input reset, or a renderer reset.API reference →);
</script>
<Sheetwriteconst 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 →{columnscolumns: readonly SimpleColumn<Record<string, CellScalar>>[]let columns:readonlySimpleColumn<Record<string, CellScalar>>[]let columns:readonlySimpleColumn<Record<string, CellScalar>>[]Restrict to these column indices (defaults to all columns).API reference →}defaultRows={rowsconst rows: readonly Record<string, CellScalar>[]constrows:readonlyRecord<string, CellScalar>[]constrows:readonlyRecord<string,CellScalar>[]end-exclusive row rangeAPI reference →} onGridChange={persistconst persist: (transaction: Transaction) => voidconstpersist: (transaction:Transaction) =>voidconstpersist: (transaction:Transaction,) =>void} onReady={handleReadyconst handleReady: ({ grid, generation, reason }: GridReadyEvent) => voidconsthandleReady: ({grid,generation,reason,}:GridReadyEvent) =>voidconsthandleReady: ({grid,generation,reason,}:GridReadyEvent) =>void} />
Svelte advanced grid
<scriptlang="ts">
importtype { Gridinterface GridinterfaceGridinterfaceGridImperative grid handle for document commands, events, rendering, and teardown.API reference → } from"@sheetwrite/core";
importtype { GridReadyEventinterface GridReadyEventinterfaceGridReadyEventinterfaceGridReadyEventGrid handle, generation, and reason published after adapter initialization.API reference → } from"@sheetwrite/core/adapter";
let gridRef:Gridinterface GridinterfaceGridinterfaceGridImperative grid handle for document commands, events, rendering, and teardown.API reference →|undefined;
consthandleReadyconst handleReady: ({ grid }: GridReadyEvent) => voidconsthandleReady: ({ grid }:GridReadyEvent) =>voidconsthandleReady: ({grid,}:GridReadyEvent) =>void= ({ gridgrid: Gridlet grid:Gridlet grid:GridLive handle just published by the adapter; replaced on the next reset generation.API reference → }:GridReadyEventinterface GridReadyEventinterfaceGridReadyEventinterfaceGridReadyEventGrid handle, generation, and reason published after adapter initialization.API reference →) =>connectconst connect: (grid: Grid) => voidconstconnect: (grid:Grid) =>voidconstconnect: (grid:Grid,) =>void(gridgrid: Gridlet grid:Gridlet grid:GridLive handle just published by the adapter; replaced on the next reset generation.API reference →);
</script>
<SheetwriteGridconst SheetwriteGrid: Component<SheetwriteGridProps, {}, "grid">constSheetwriteGrid:Component<SheetwriteGridProps,{},"grid">constSheetwriteGrid:Component<SheetwriteGridProps,{},"grid">Advanced framework component for workbook data or datasource input.API reference →bind:gridgrid: Grid | nulllet grid:Grid|nulllet grid:Grid|nullLive handle just published by the adapter; replaced on the next reset generation.API reference →={gridRefconst gridRef: Grid | nullconstgridRef:Grid|nullconstgridRef:Grid|null} {workbookworkbook: Workbooklet workbook:Workbooklet workbook:WorkbookLive workbook schema adopted by the store and updated by document operations.API reference →}{datasourcedatasource: DataSourcelet datasource:DataSourcelet datasource:DataSourceLazy row provider requested for visible windows; use instead of eager data.API reference →}onReady={handleReadyconst handleReady: ({ grid }: GridReadyEvent) => voidconsthandleReady: ({ grid }:GridReadyEvent) =>voidconsthandleReady: ({grid,}:GridReadyEvent) =>void} />
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.
Persist committed transactions
functionpersist(event:ChangeEventinterface ChangeEventinterfaceChangeEventinterfaceChangeEventPayload of the change event; flows OUT for API submission/reconcile.API reference →):void {
if (eventevent: ChangeEventlet event:ChangeEventlet event:ChangeEvent.sourceChangeEvent.source: OperationSourceinterfaceChangeEvent {source:OperationSource;}interfaceChangeEvent {source:OperationSource;}Remote input is observable but never belongs in outgoing local persistence.API reference →==="local") operationQueueconst operationQueue: {
push(...patches: Transaction["patches"]): void;
}constoperationQueue: {push(...patches:Transaction["patches"]):void;}constoperationQueue: {push(...patches:Transaction["patches"]):void;}.pushfunction push(...patches: Transaction["patches"]): voidfunctionpush(...patches:Transaction["patches"]):voidfunctionpush(...patches:Transaction["patches"]):void(...eventevent: ChangeEventlet event:ChangeEventlet event:ChangeEvent.transactionChangeEvent.transaction: TransactioninterfaceChangeEvent {transaction:Transaction;}interfaceChangeEvent {transaction:Transaction;}Operations that actually committed after policy and bounds filtering.API reference →.patchesTransaction.patches: DocumentOp[]interfaceTransaction {patches:DocumentOp[];}interfaceTransaction {patches:DocumentOp[];}Ordered document operations submitted as one store commit.API reference →);
}
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.