Skip to content

Recipe: Displaying data

Goal: show the results of an Arc query in a table — and have it update on its own when the underlying read model changes.

If your query is observable, DataTableForObservableQuery subscribes for you and re-renders as new data arrives — no polling, no manual subscription:

import { Column, DataTableForObservableQuery } from '@cratis/components/DataTables';
import { AllAuthors } from './Authors/Author'; // generated observable query proxy
export const Authors = () => (
<DataTableForObservableQuery query={AllAuthors} emptyMessage="No authors yet">
<Column field="name" header="Name" sortable />
<Column field="id" header="Id" />
</DataTableForObservableQuery>
);

While the first result is loading without rows, the table shows Loading…. A failed or unauthorized query shows an alert instead of emptyMessage; a successful empty result shows emptyMessage. You can change these messages with loadingMessage, failureMessage, and unauthorizedMessage, or configure provider defaults. During a refetch the existing rows remain visible and the table is marked busy. For a one-shot (non-live) query, use DataTableForQuery the same way.

Prefer the hook when you need the data, not a table

Section titled “Prefer the hook when you need the data, not a table”

When you want the values themselves (to filter, summarize, or render custom markup), call .use() on the proxy:

import { AllAuthors } from './Authors/Author';
export const AuthorCount = () => {
const [authors] = AllAuthors.use();
if (!authors.isAuthorized) return <p>You don't have access to the author list.</p>;
if (authors.hasExceptions) return <p role='alert'>Couldn't load authors.</p>;
if (authors.isPerforming && !authors.hasData) return <p>Loading…</p>;
return <p>{authors.data.length} authors</p>;
};

For the common “table on the left, details on the right” screen, DataPage gives you the layout, selection, and a resizable detail panel out of the box:

import { DataPage } from '@cratis/components/DataPage';

See DataPage for menu items, the details panel, and selection wiring.

  • When the table updates — an observable table re-renders when the query’s source reports a change. With a direct database backend that happens after the write; with Chronicle, the read model updates shortly after a command appends its event, once the projection catches up. See Read Models.
  • Keep read models specialized per screen — a table query and a detail query can read different, purpose-built read models rather than one shared model.
  • Building a form — the write side
  • DataTables — choose the Arc query wrapper and configure columns
  • DataPage — compose a query-backed list screen with actions and details