2.5 KiB
Reference Data Layer
Table of Contents
Purpose
The refdata/ layer contains app-wide reference datasets that are reused across modules.
Reference data is data that usually comes from the backend, but is not owned by one feature module.
Examples:
- countries
- languages
- currencies
- time zones
- common option dictionaries
- shared lookup datasets
Responsibilities
The refdata/ layer is responsible for:
- fetching common reference datasets
- exposing reusable query hooks for those datasets
- defining cache keys for reference data
- keeping app-wide lookup data out of feature modules
Recommended Structure
For small datasets, a single file per dataset is enough:
refdata/
├── countries.ts
├── languages.ts
└── currencies.ts
For larger datasets, use a folder:
refdata/
└── countries/
├── api.ts
├── dto.ts
├── mapper.ts
├── queries.ts
└── keys.ts
Rules
-
Use
refdata/only for app-wide datasets.If a dataset belongs to one feature module, keep it in that module's
data/layer. -
refdata/may use infrastructure.Reference data hooks can use
#infrastructure/axiosand#infrastructure/reactQuery. -
refdata/should not import fromview/,pages/, or feature modules.It should remain reusable across the app.
-
Expose hooks or small service functions.
Consumers should not need to know backend endpoints or cache key details.
-
Add mappers when backend DTOs differ from app-facing reference data.
If a reference dataset performs DTO transformation, test the mapper the same way module data mappers are tested.
Examples
import { keepPreviousData, useQuery } from "@tanstack/react-query";
import { axiosClient } from "#infrastructure/axios";
import { createKeyBuilder } from "#infrastructure/reactQuery";
export const countriesCacheKey = createKeyBuilder(
"REF_DATA",
"COUNTRIES",
"LIST",
);
interface CountryData {
code: string;
name: string;
}
export const useCountries = () => {
return useQuery({
queryKey: countriesCacheKey.store(),
placeholderData: keepPreviousData,
queryFn: async () => {
return axiosClient
.get<Array<CountryData>>("/datasets/countries")
.then((data) => data.data);
},
});
};