# useDocyrusTenant
URL: /docs/web/hooks/use-docyrus-tenant
Single-line tenant integration that fetches tenant preferences, builds dateUtils + numberUtils, and wires DateFormatProvider + NumberFormatProvider so every UI component (data grids, calendars, filters, value renderers) picks up the tenant's configured date/time/number formats automatically.
## Installation
```bash
pnpm dlx @docyrus/cli add @docyrus/hooks-use-docyrus-tenant
```
**Dependencies:**
- [@docyrus/app-utils](https://www.npmjs.com/package/@docyrus/app-utils)
- [@docyrus/api-client](https://www.npmjs.com/package/@docyrus/api-client)
- [@tanstack/react-query](https://tanstack.com/query/latest)
This module ships two named exports:
- `
);
}
```
From there, every UI component that reads `useDateFormat()` / `useNumberFormat()` — including [`useDocyrusDataGrid`](/docs/web/hooks/use-docyrus-data-grid), [`useDocyrusDataTable`](/docs/web/hooks/use-docyrus-data-table), [`useDocyrusDataGallery`](/docs/web/hooks/use-docyrus-data-gallery), calendar event cells, side-filter chips, and the standalone value renderers — picks up the tenant's configured formats automatically. **No per-page formatter wiring required.**
For ad-hoc formatting (custom chart axes, header labels, etc.) read the same utils via the hook:
```tsx
import { useDocyrusTenant } from '@docyrus/ui/library/hooks/use-docyrus-tenant';
function ChartHeader({ date }: { date: string }) {
const { dateUtils, isLoading } = useDocyrusTenant();
if (isLoading || !dateUtils) return —;
return {dateUtils.formatDateLong(date)};
}
```
## Provider props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `client` | `RestApiClient \| null \| undefined` | — | The `@docyrus/api-client` instance used to fetch `/v1/tenant/preferences`. |
| `enabled` | `boolean` | `Boolean(client)` | Defer the fetch until your auth flow is ready. Set to `false` (or leave `client` null) until the user is authenticated. |
| `userTimezone` | `string` | `'UTC'` | IANA timezone id forwarded to `createDateUtils`. Typically the user profile's `timeZone.id`. |
| `staleTime` | `number` | `1_800_000` (30 min) | TanStack Query stale window for the preferences query. |
| `children` | `ReactNode` | — | App tree to wrap. |
## Hook return
`useDocyrusTenant()` returns:
| Field | Type | Description |
|-------|------|-------------|
| `preferences` | `TenantPreferences \| null` | Normalized tenant preferences (camelCase keys mirrored to snake_case). `null` until the fetch finishes. |
| `dateUtils` | `DateUtils \| null` | Output of `createDateUtils({ preferences, userTimezone })`. Exposes `formatDate`, `formatDateTime`, `formatDateLong`, `toUserTimezone`. |
| `numberUtils` | `NumberUtils \| null` | Output of `createNumberUtils({ preferences })`. Exposes `formatNumber`. |
| `isLoading` | `boolean` | TanStack Query's loading flag for the preferences fetch. |
## Auto-wired contexts
Internally `` mounts:
```text
DocyrusTenantContext.Provider
└── DateFormatProvider (formatDate / formatDateTime / formatTime)
└── NumberFormatProvider (formatNumber)
└── {children}
```
Every Docyrus UI component reads from these contexts:
| Consumer | Context | Effect |
|----------|---------|--------|
| `useDocyrusDataGrid` / `useDocyrusDataTable` / `useDocyrusDataGallery` | `useDateFormat()` + `useNumberFormat()` | Date / datetime / number cells pick up tenant formatting unless a `formatDate` / `formatDateTime` / `formatNumber` prop is passed explicitly (props still win). |
| Calendar event cells, side-filter chips | `useDateFormat()` | Same fallback chain. |
| `DocyrusDateValue`, `DocyrusDateTimeValue`, `DocyrusNumberValue` value renderers | `useDateFormat()` / `useNumberFormat()` | Standalone display components inherit tenant formatting. |
**Backwards compatible:** the data-grid / data-table hooks detect whether a real provider is mounted (vs. the no-provider sentinel) before injecting the context formatter. Apps that haven't adopted `` yet keep their previous behaviour byte-for-byte — the cells fall back to their internal `Intl.NumberFormat` / raw-string renderers exactly as before.
## Standalone `normalizeTenantPreferences`
If you maintain your own provider stack (for example you also need to seed a non-Docyrus formatter), you can call the helper directly:
```tsx
import {
normalizeTenantPreferences,
type DocyrusTenantContextValue
} from '@docyrus/ui/library/hooks/use-docyrus-tenant';
import {
createDateUtils,
createNumberUtils,
getTenantPreferences
} from '@docyrus/app-utils';
const envelope = await getTenantPreferences(client);
const preferences = normalizeTenantPreferences(envelope);
if (preferences) {
const dateUtils = createDateUtils({ preferences, userTimezone });
const numberUtils = createNumberUtils({ preferences });
// …wire them into your own context
}
```
The helper accepts either the full envelope (`{ preferences, tenant, product, enums }`) or an already inner-shaped object and is safe to call with `null` / `undefined` (returns `null`).
## Type Exports
| Type | Description |
|------|-------------|
| `DocyrusTenantContextValue` | Shape returned by `useDocyrusTenant()`. |
| `DocyrusTenantProviderProps` | Props accepted by ``. |