Remote Data with Fetchit
Problem
The fetch callback inside createRemoteSource() is a plain function — it has no retry logic, no shared auth headers, and no base URL configuration. Duplicating HTTP settings in both a Fetchit API client and the source's fetch callback creates two places to update when the API changes.
Solution
Pass a Fetchit api.get() call as the fetch function. Fetchit handles auth, retries, and base URL; Sourceit handles pagination and query state.
ts
import { createApi } from '@vielzeug/fetchit';
import { createRemoteSource } from '@vielzeug/sourceit';
type Issue = { id: number; name: string; status: 'open' | 'closed' };
type Filter = { status?: 'open' | 'closed' };
type Sort = { by: 'name' | 'updatedAt'; dir: 'asc' | 'desc' };
const api = createApi({
baseUrl: '/api',
headers: { Accept: 'application/json' },
});
const source = createRemoteSource<Issue, Filter, Sort>({
fetch: async ({ filter, limit, page, search, sort }) => {
const response = await api.get<{ items: Issue[]; total: number }>('/issues', {
query: {
filter: filter ? JSON.stringify(filter) : undefined,
limit,
page,
search,
sort: sort ? JSON.stringify(sort) : undefined,
},
});
return { items: response.items, total: response.total };
},
filter: { status: 'open' },
sort: { by: 'updatedAt', dir: 'desc' },
limit: 25,
});
source.refresh();
await source.ready();
console.log(source.current, source.meta.totalItems);Pitfalls
- Fetchit's
api.get()throws on HTTP errors (4xx/5xx). Wrap the call in try/catch inside thefetchcallback and return{ items: [], total: 0 }so Sourceit can surface its error state rather than crashing. - Filter and sort objects are passed as JSON-stringified query params in this example — verify the server expects this format before adapting.
source.refresh()is non-blocking. Always awaitsource.ready()before readingsource.currentif you need the initial data synchronously.