Skip to content

State and resource ownership

Decide who owns each value before connecting a table to a request Hook. A component can protect its own state from stale results without owning your data source or undoing server work.

Application, Hook, and table

Arrows below name data passed or actions requested. They are ownership interactions, not package dependencies. The application may compose Hooks with View/Viewer; the diagram does not imply that every table creates a Hook.

mermaid
flowchart LR
  App[Application] -->|creates executor and handles errors| Hook[React Hook]
  Hook -->|loading result error| UI[Application UI]
  App -->|dataSource and optional controlled state| Table[Viewer or View]
  Table -->|load and interaction callbacks| App
  App -->|persistence commands| Server[Application service]
  Server -->|rows and save outcome| App
  App -->|save success callback| Table
  classDef default fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
State or resourceOwner and update pathCleanup or limit
Hook loading/result/error/statususeExecutePromise commits only the latest request while mountedNew execution aborts the previous controller; unmount aborts; executor must use the controller to stop real work
Hook exchangeuseFetcher retains exchange and selects explicit or registered clientShared client state has its own lifetime
Rows and totalApplication passes PagedList through dataSourceView does not filter, sort, or page the supplied rows automatically
Single-view interaction stateView manages it internally unless external value/update callbacks control itApplication handles resulting queries and supplies the next data
View collection and active viewViewer manages collection/selection and requests data through onLoadDataPersistence remains in application callbacks

Hook behavior: packages/react/src/core/useExecutePromise.ts:210, packages/react/src/core/useExecutePromise.ts:320, and packages/react/src/fetcher/useFetcher.ts:162. reset() only sets idle state; it does not abort or invalidate an active execution (packages/react/src/core/useExecutePromise.ts:309). Table ownership: packages/viewer/src/view/View.tsx:106, packages/viewer/src/view/hooks/useViewState.ts:285, and packages/viewer/src/viewer/Viewer.tsx:199.

Saving a view has an explicit confirmation boundary

With Viewer, the application implements onCreateView, onUpdateView, and onDeleteView. Viewer changes its local collection/selection only when the application invokes the supplied success callback. Call it after the persistence outcome your application requires, and display failures yourself. Clicking Save is not default persistence. See packages/viewer/src/viewer/Viewer.tsx:140 and saved-view guide.

FetcherViewer connects a specific backend protocol. For creation and update it waits for the Wow command to reach PROCESSED, rereads the view snapshot, and confirms matching aggregate/tenant/owner identity, definitionId, and a finite snapshot.version >= aggregateVersion before invoking success. Missing or lagging versions produce an unconfirmed/retry state. Deletion rereads and invokes its callback without the same version confirmation. See packages/viewer/src/fetcherviewer/FetcherViewer.tsx:202, packages/viewer/src/fetcherviewer/FetcherViewer.tsx:382, packages/viewer/src/fetcherviewer/FetcherViewer.tsx:461, and packages/viewer/src/fetcherviewer/FetcherViewer.tsx:514.

That confirmation applies to these view mutations, not arbitrary row queries or a general read-your-writes guarantee. It places no upper bound on projection delay.

Identity changes and disposal

FetcherViewer remounts its inner state for definitionId/tenantId/ownerId changes. Its mutation marker ignores old create/update command completions after unmount; deletion does not check the same marker. Remote row loading POSTs a PagedQuery, combines internalCondition with interaction conditions, and exposes data only for the current request object. These protect UI state; they do not authorize access or revoke server commands. See packages/viewer/src/fetcherviewer/FetcherViewer.tsx:103, packages/viewer/src/fetcherviewer/FetcherViewer.tsx:188, and packages/viewer/src/fetcherviewer/hooks/useFetchData.ts:53.

ResourceWhat disposal doesWhat its creator still owns
React event subscriptionEffect cleanup removes that subscriptionShared bus lifetime
KeyStoragedestroy() removes its own event handlerPersistent data and any shared event bus; default serial bus is local, not cross-tab synchronization
BroadcastTypedEventBusdestroy() closes its messengerAppropriate lifetime of shared users before closing it

See packages/react/src/eventbus/useEventSubscription.ts:94, packages/storage/src/keyStorage.ts:237, packages/storage/src/keyStorage.ts:466, and packages/eventbus/src/broadcastTypedEventBus.ts:236. Follow React cleanup, remote data, FetcherViewer reference, and SSR scope.

Released under the Apache License 2.0.