# useDocyrusPivotGrid URL: /docs/native/hooks/use-docyrus-pivot-grid Pivot grid backed by a Docyrus data source. Aggregates on the device from raw records, or in the database through a pivot matrix and calculations, and returns a controller for the native PivotGrid components. ## Installation ```bash pnpm dlx @docyrus/cli add @docyrus/rn-hooks-use-docyrus-pivot-grid ``` **Dependencies:** - [@docyrus/api-client](https://www.npmjs.com/package/@docyrus/api-client) - [@tanstack/react-query](https://tanstack.com/query/latest) A straight port of the web hook, with the same signature. It fetches `/v1/apps/{appSlug}/data-sources/{dataSourceSlug}/items` through TanStack Query and feeds the rows into the native [rn-pivot-grid](/docs/native/docyrus/pivot-grid). The result's `controller` plugs into `PivotGridView`, `PivotGridToolbar`, `PivotGridExportMenu` and `PivotGridDrilldownModal`. It needs an authenticated `RestApiClient` and a `QueryClientProvider` above it. Two aggregation modes are available: - **`'client'`** (default): fetches raw records (`columns` is auto-derived from the dimensions and measures, `limit` defaults to 5000) and aggregates on the device. Simple, but not suited to large datasets. - **`'server'`**: sends a `pivot.matrix` + `calculations` payload so the database aggregates. The response has one row per dimension combination, so it scales to any dataset size. A date dimension with `dateFormat` is bucketed on the server with `to_char[format]@field` over a `dateRange` axis. ## Usage ```tsx import { useMemo } from 'react'; import { View } from 'react-native'; import { useDocyrusClient } from '@docyrus/signin/react-native'; import { PivotGridDrilldownModal, PivotGridToolbar, PivotGridView } from '@/components/docyrus-native/pivot-grid'; import { useDocyrusPivotGrid } from '@/hooks/docyrus-native/use-docyrus-pivot-grid'; export function TimeEntryReport() { const client = useDocyrusClient(); const rowDimensions = useMemo(() => [ { id: 'user', label: 'User', field: 'record_owner', subField: 'name', emptyLabel: 'Unassigned' } ], []); const columnDimensions = useMemo(() => [ { id: 'month', label: 'Month', field: 'date', dateFormat: 'YYYY-MM', dateRange: { interval: 'day', min: '2026-01-01', max: '2026-06-30' } } ], []); const measures = useMemo(() => [ { id: 'logged', label: 'Logged (h)', field: 'duration', aggregate: 'sum' as const, transform: (s: number) => s / 3600 } ], []); const { controller, isLoading, error, refetch } = useDocyrusPivotGrid({ client: client!, appSlug: 'base', dataSourceSlug: 'time_entry', mode: 'server', rowDimensions, columnDimensions, measures, height: 420, enabled: Boolean(client) }); return ( ); } ``` Memoize `rowDimensions`, `columnDimensions` and `measures`. They are part of the query payload and the pivot structure, so new arrays on every render rebuild both. ## API Reference ### Options (`UseDocyrusPivotGridOptions`) | Option | Type | Default | Description | |--------|------|---------|-------------| | `client` | `RestApiClient` | — | Authenticated API client. Required. | | `appSlug` | `string` | — | App slug of the data source. Required. | | `dataSourceSlug` | `string` | — | Data source slug. Required. | | `mode` | `'client' \| 'server'` | `'client'` | Where to aggregate. | | `rowDimensions` | `DocyrusPivotGridDimension[]` | — | Row grouping dimensions (outermost → innermost). Required. | | `columnDimensions` | `DocyrusPivotGridDimension[]` | — | Column grouping dimensions. Required. | | `measures` | `DocyrusPivotGridMeasure[]` | — | Measures aggregated in each cell. Required. | | `columns` | `string` | auto | `columns` expression. In client mode it is auto-derived from the dimensions and measures (relation dimensions become `...field(subField)`). In server mode the default is `'id'`. | | `filters` | `unknown` | — | Server-side filters forwarded verbatim. | | `orderBy` | `string` | — | `orderBy` expression. Client mode only. | | `limit` | `number` | `5000` | Maximum records fetched. Client mode only. | | `getRowId` | `(row: TData, index: number) => string` | — | Stable row id forwarded to `usePivotGrid`. | | `initialState` | `Partial` | — | Initial expand, pin and size state. | | `cellColorRules` | `PivotGridCellColorRule[]` | — | JSONata cell color rules. | | `drilldown` | `PivotGridDrilldown` | — | Drilldown configuration (`NativeDrilldownColumn` columns). | | `height` | `number \| 'auto'` | `600` | Grid height in px. Native has no auto height (the list is virtualized), so `'auto'` resolves to `600`. | | `className` | `string` | — | Container classes, applied by `PivotGridView`. | | `exportFileName` | `string` | `'pivot-grid'` | Native only. Base file name for CSV, Excel and PDF exports. | | `enabled` | `boolean` | `true` | Enable the query. It also waits for `client`, `appSlug` and `dataSourceSlug`. | | `staleTime` | `number` | `30_000` | TanStack Query stale time in ms. | The query key is `['docyrus', 'pivot-grid', mode, appSlug, dataSourceSlug, payload]`. ### DocyrusPivotGridDimension | Field | Type | Description | |-------|------|-------------| | `id` | `string` | Unique id. In server mode the column alias is `dim_`. | | `label` | `string` | Header label. | | `field` | `string` | Field slug on the data source. | | `subField` | `string` | Sub-field of a relation (for example `'name'` for `record_owner.name`). | | `dateFormat` | `string` | Server mode. Postgres `to_char` format (`'YYYY-MM'`, `'YYYY'`) for date bucketing. | | `dateRange` | `{ interval: string; increment?: number; min: string; max: string }` | Needed with `dateFormat`. The date axis passed to the pivot matrix. | | `getValue` | `(row: TData) => unknown` | Custom value extractor. Takes precedence over the automatic accessor. | | `formatValue` | `(value: unknown) => string` | Label formatter. | | `sort` | `(a: unknown, b: unknown) => number` | Sort comparator. | | `emptyLabel` | `string` | Label for empty values. | ### DocyrusPivotGridMeasure | Field | Type | Description | |-------|------|-------------| | `id` | `string` | Unique id. Also the server calculation alias. | | `label` | `string` | Header label. | | `field` | `string` | Field to aggregate (`'id'` for `count`). | | `aggregate` | `'sum' \| 'count' \| 'avg' \| 'min' \| 'max'` | Aggregation function. | | `transform` | `(value: number) => number` | Applied after reading the value (for example seconds → hours). | | `getValue` | `(row: TData) => number \| null \| undefined` | Custom extractor. Takes precedence over `field`. | | `formatValue` | `(value: number) => string` | Cell formatter. | ### Result (`UseDocyrusPivotGridResult`) | Field | Type | Description | |-------|------|-------------| | `controller` | `PivotGridController` | Pass it to `PivotGridView`, `PivotGridToolbar`, `PivotGridExportMenu` and `PivotGridDrilldownModal`. | | `items` | `TData[]` | Rows returned by the API: raw records in client mode, aggregated rows in server mode. | | `isLoading` | `boolean` | First load in progress. | | `isFetching` | `boolean` | Any fetch in progress (including refetches). | | `error` | `Error \| null` | Query error. | | `refetch` | `() => void` | Refetch the items. | ## Differences from web - `height` is a pixel value. `'auto'` falls back to `600`. - `className` is forwarded through the controller and applied by `PivotGridView`. - `drilldown.columns` are `NativeDrilldownColumn`s (`{ id, header, getValue }`) instead of TanStack `ColumnDef`s. - Adds `exportFileName` for the share-sheet exports. ## Type Exports | Type | Description | |------|-------------| | `UseDocyrusPivotGridOptions` | Hook options. | | `UseDocyrusPivotGridResult` | Hook result. | | `DocyrusPivotGridDimension` | Docyrus-field dimension descriptor. | | `DocyrusPivotGridMeasure` | Docyrus-field measure descriptor. | | `DocyrusPivotGridMode` | `'client' \| 'server'`. | | `PivotRow` | `Record` (default row type). | | `PivotGridAggregate` | Re-exported aggregate union. |