Reference Data — Lookup Tables for React
@granit/reference-data provides framework-agnostic types and API functions for
any reference-data entity — countries, product categories, document types,
anything backed by Granit.ReferenceData on the .NET side. The contract is
generic: one ReferenceDataEntry shape, one query type, one set of endpoints.
@granit/react-reference-data exposes a hook factory: you call it once per
entity type and get a typed set of TanStack Query hooks back. There are no
per-entity packages and no useCountries-style hardcoded hooks.
Peer dependencies: axios, react ^19, @tanstack/react-query ^5
Package structure
Section titled “Package structure”Directory@granit/reference-data/ Generic entry types, query params, API functions (framework-agnostic)
- @granit/react-reference-data
createReferenceDataHooks()factory
- @granit/react-reference-data
| Package | Role | Depends on |
|---|---|---|
@granit/reference-data | ReferenceDataEntry, ReferenceDataQuery, listReferenceData(), getReferenceDataEntry(), … | — |
@granit/react-reference-data | createReferenceDataHooks() | @granit/reference-data, @tanstack/react-query, axios, react |
import { createReferenceDataHooks } from '@granit/react-reference-data';import type { ReferenceDataEntry } from '@granit/reference-data';import { api } from './api-client';
// Call the factory once per entity — the name is the plural, kebab-cased// backend route segment. Base path defaults to// `/api/v1/reference-data/countries`.interface Country extends ReferenceDataEntry {}const countries = createReferenceDataHooks<Country>('countries');
function CountrySelect() { const { data, isLoading } = countries.useList({ client: api, params: { activeOnly: true }, });
// data is a PagedResult<Country> — render data.items}import { listReferenceData, getReferenceDataEntry } from '@granit/reference-data';import type { ReferenceDataEntry, ReferenceDataQuery } from '@granit/reference-data';TypeScript SDK
Section titled “TypeScript SDK”interface ReferenceDataEntry extends ReferenceDataLabels { readonly id: ReferenceDataEntryId; readonly code: string; /** Resolved label for the current UI culture (server-computed, not persisted). */ readonly label: string; readonly activated: boolean; readonly sortOrder: number; readonly validFrom: ISODateString | null; readonly validTo: ISODateString | null; /** Parent code for hierarchical types (null for root entries). */ readonly parentCode: string | null; /** Custom properties bag (all values are strings). */ readonly metadata: Record<string, string> | null;}
interface ReferenceDataQuery extends PaginationParams { readonly activeOnly?: boolean; // default: true readonly search?: string; // free-text on code and labels readonly sortBy?: string; // default: 'SortOrder' readonly descending?: boolean; // default: false}Entity-specific fields go in metadata (all values are strings) or in your own
interface extending ReferenceDataEntry — the framework does not ship an
ISO-3166 Country type.
API functions
Section titled “API functions”| Function | Endpoint | Purpose |
|---|---|---|
listReferenceData(client, basePath, params?) | GET {basePath} | Paginated list — returns PagedResult<T> |
getReferenceDataEntry(client, basePath, code) | GET {basePath}/{code} | Single entry by code |
listReferenceDataChildren(client, basePath, code) | GET {basePath}/{code}/children | Children of a hierarchical entry |
createReferenceDataEntry(client, basePath, request) | POST {basePath} | Create |
updateReferenceDataEntry(client, basePath, code, request) | PUT {basePath}/{code} | Update |
deactivateReferenceDataEntry(client, basePath, code) | DELETE {basePath}/{code} | Soft-delete |
React bindings
Section titled “React bindings”createReferenceDataHooks(entityName, options?)
Section titled “createReferenceDataHooks(entityName, options?)”function createReferenceDataHooks<T extends ReferenceDataEntry>( /** Plural, kebab-cased entity name matching the backend route segment. */ entityName: string, factoryOptions?: { readonly defaultBasePath?: string }): { keys: ReferenceDataKeys; useList: (options: ReferenceDataListHookOptions) => UseQueryResult<PagedResult<T>>; useEntry: (code: string, options: ReferenceDataHookOptions) => UseQueryResult<T>; useChildren: (parentCode: string, options: ReferenceDataHookOptions) => UseQueryResult<T[]>; useCreate: (options: ReferenceDataMutationHookOptions) => UseMutationResult<void, Error, ReferenceDataCreateRequest>; useUpdate: (options: ReferenceDataMutationHookOptions) => UseMutationResult<void, Error, ReferenceDataUpdateVariables>; useDeactivate: (options: ReferenceDataMutationHookOptions) => UseMutationResult<void, Error, string>;};defaultBasePath falls back to /api/v1/reference-data/{entityName}; every hook
accepts a per-call basePath override.
Hook options
Section titled “Hook options”interface ReferenceDataListHookOptions { client: AxiosInstance; basePath?: string; params?: ReferenceDataQuery; enabled?: boolean; // default: true}Mutations
Section titled “Mutations”Mutations resolve to void and invalidate the affected queries on success:
useCreate invalidates the lists, useUpdate and useDeactivate invalidate the
lists plus that entry’s detail key.
interface ReferenceDataCreateRequest extends Partial<ReferenceDataLabels> { readonly code: string; readonly labelEn: string; readonly sortOrder?: number; readonly validFrom?: ISODateString | null; readonly validTo?: ISODateString | null; readonly parentCode?: string | null; readonly metadata?: Record<string, string> | null;}
// useUpdate takes { code, data: ReferenceDataUpdateRequest }Query keys
Section titled “Query keys”The factory returns a keys object scoped to the entity name:
const countries = createReferenceDataHooks<Country>('countries');
countries.keys.all; // ['reference-data', 'countries']countries.keys.lists(); // [...all, 'list']countries.keys.list(params); // [...lists(), params]countries.keys.detail('BE'); // [...all, 'detail', 'BE']countries.keys.children('EU'); // [...all, 'children', 'EU']Public API summary
Section titled “Public API summary”| Category | Key exports | Package |
|---|---|---|
| Types | ReferenceDataEntry, ReferenceDataQuery, ReferenceDataCreateRequest, ReferenceDataUpdateRequest | @granit/reference-data |
| API functions | listReferenceData(), getReferenceDataEntry(), listReferenceDataChildren(), createReferenceDataEntry(), updateReferenceDataEntry(), deactivateReferenceDataEntry() | @granit/reference-data |
| Hook factory | createReferenceDataHooks() | @granit/react-reference-data |
See also
Section titled “See also”- .NET counterpart: Reference Data — the server-side module behind this package
- Granit.ReferenceData module — .NET reference data with i18n labels and CRUD endpoints
- Localization — Country labels use the same multilingual pattern