Skip to Content
Welcome to the official DBS Documentation! 📚
Core Building BlocksData Fetching

Data Fetching

DBS standardizes all client-side data fetching through a set of custom SWR-based hooks. This ensures consistent loading, error, and caching behavior throughout the dashboard.

Core Hook: useData

useData is the fundamental building block — a typed SWR wrapper for any GET request.

// src/hooks/use-data.ts import { useData } from '@/hooks/use-data';

Signature

function useData<T>( key: string | null, fetcher: () => Promise<T>, options?: { transform?: (data: T) => T; refreshInterval?: number; revalidateOnFocus?: boolean; } ): { data: T | undefined; isLoading: boolean; error: Error | undefined; mutate: () => void; }

Usage

import { useData } from '@/hooks/use-data'; import { usersApi } from '@/services/users/api'; export function UsersList() { const { data: users, isLoading, error } = useData( 'users-list', () => usersApi.getUsers() ); if (isLoading) return <Spinner />; if (error) return <ErrorState />; return users?.map(user => <UserRow key={user.id} user={user} />); }

The key parameter functions as a SWR cache key. Choose unique, deterministic keys (e.g., users-list, team-${teamId}). Use the same key across components to share cached data automatically.

useDataTable extends useData with server-side/client-side sort, filter, search, and pagination — all wired together.

import { useDataTable } from '@/hooks/use-data-table'; import { usersApi } from '@/services/users/api'; export function UsersTable() { const { data, // Current page data isLoading, error, // Pagination page, pageSize, totalPages, totalItems, setPage, setPageSize, // Sorting sortKey, sortOrder, setSortKey, setSortOrder, // Filtering search, setSearch, filters, setFilter, } = useDataTable({ key: 'users-table', fetcher: () => usersApi.getUsers(), defaultPageSize: 20, searchKeys: ['name', 'email'], defaultSort: { key: 'createdAt', order: 'desc' }, }); return ( <AppTable data={data} isLoading={isLoading} columns={columns} pagination={{ page, pageSize, totalPages, setPage }} /> ); }

Pagination: usePagination

A lightweight hook for managing pagination state when you need it independently of the fetcher:

import { usePagination } from '@/hooks/use-pagination'; export function PaginatedList() { const { page, pageSize, setPage, setPageSize } = usePagination({ defaultPage: 1, defaultPageSize: 10, }); const { data } = useData( `items-page-${page}`, () => itemsApi.getItems({ page, pageSize }) ); return ( <> <ItemList items={data?.items} /> <Pagination page={page} total={data?.total} setPage={setPage} /> </> ); }

Audit Logs: useAuditLogs

A specialized hook for the audit log viewer:

import { useAuditLogs } from '@/hooks/use-audit-logs'; export function AuditLogViewer() { const { logs, isLoading, filters, setFilter } = useAuditLogs({ defaultFilters: { userId: undefined, action: undefined }, }); return ( <LogTable logs={logs} isLoading={isLoading} onFilterChange={setFilter} /> ); }

Session: useSession

Access the current user’s session and profile:

import { useSession } from '@/hooks/use-session'; // or directly from auth-client: import { useSession } from '@/lib/auth-client'; export function UserProfile() { const { data: session, isPending } = useSession(); return ( <div> <p>{session?.user.name}</p> <p>{session?.user.email}</p> </div> ); }

Mutating Data

For POST, PUT, DELETE requests, use a useMutation-style pattern. SWR’s mutate() function is used to invalidate cache after a successful mutation:

import { useData } from '@/hooks/use-data'; import { usersApi } from '@/services/users/api'; export function DeleteUserButton({ userId }) { const { mutate } = useData('users-list', () => usersApi.getUsers()); const handleDelete = async () => { await usersApi.deleteUser(userId); await mutate(); // Re-fetch the users list }; return <Button onClick={handleDelete}>Delete</Button>; }

Services Layer

All API calls go through typed client functions in src/services/. Never call fetch() directly in components:

ServiceMethods
usersApigetUsers(), getUser(id), assignRole(), syncUserRoles()
teamsApigetTeams(), createTeam(), updateTeam(), addMember(), removeMember()
accessApigetRoles(), getPermissions(), createRole(), updateRole(), syncPermissions()
notificationsApigetNotifications(), markAsRead(), markAllAsRead(), deleteNotification()
tasksApicreateTask(), getTask(id)
Last updated on