A react-admin data provider backed by TanStack DB, and a simple REST collection to sync it with an API.
React Admin queries a local TanStack DB database instead of hitting the network on every page. Filtering, sorting, pagination and mutations all run against local collections; the collection layer owns synchronization with the backend.
This is an exploratory project, see its Limitations.
| Package | Description |
|---|---|
ra-data-tanstack-db |
ra-core data provider reading and writing TanStack DB collections. |
tanstack-db-simple-rest-collection |
TanStack DB collection options for a Simple REST API (filter/sort/range query params). |
Create one TanStack DB collection per react-admin resource, then pass them to
tanstackDbDataProvider.
import { Admin, Resource, type RaRecord } from "react-admin";
import { BasicIndex, createCollection } from "@tanstack/db";
import { QueryClient } from "@tanstack/react-query";
import { tanstackDbDataProvider } from "ra-data-tanstack-db";
import { simpleRestCollectionOptions } from "tanstack-db-simple-rest-collection";
const queryClient = new QueryClient();
const postsCollection = createCollection(
simpleRestCollectionOptions<RaRecord>({
queryClient,
queryKey: ["posts"],
url: "https://my.api.com/posts",
getKey: (item) => String(item.id),
defaultIndexType: BasicIndex,
syncMode: "eager",
}),
);
// An index is required on every field you sort by, `id` included.
postsCollection.createIndex((row) => row.id);
postsCollection.createIndex((row) => row.title);
const dataProvider = tanstackDbDataProvider({
collections: { posts: postsCollection },
});
export const App = () => (
<Admin dataProvider={dataProvider}>
<Resource name="posts" list={/* ... */} />
</Admin>
);getList and getManyReference translate react-admin filters into TanStack DB expressions:
| Filter key | Meaning |
|---|---|
field |
Equality. true/false also match 1/0. |
field_eq, field_neq |
Equality, inequality. |
field_gt, field_gte, field_lt, field_lte |
Comparisons. |
field_eq_any, field_neq_any |
Value in / not in a list. |
field_q |
Case-insensitive substring match, any of the given terms. |
field_inc_any |
Array field including any of the given values. |
q |
Case-insensitive substring match across all string fields. |
simpleRestCollectionOptions wraps @tanstack/query-db-collection. It translates TanStack DB subset loading into Simple REST query params (filter, sort, range) and maps mutations to POST /resource, PUT /resource/:id and DELETE /resource/:id. It accepts every queryCollectionOptions field except queryFn, plus:
url: the resource endpoint.onQuery: called with the records returned by a successful query.
Any other TanStack DB collection works with the data provider too; this one is just a convenient default.
Requires pnpm.
pnpm install
pnpm build # build both packages and the example
pnpm typecheck
pnpm lint
pnpm example # run the example appThe example/ directory is a full react-admin demo (posts, comments, tags, users) wired to the data provider against a Simple REST backend. Seeexample/src/provider/tanstackDataProvider.tsx for the complete setup.
- No live updates. React Admin's data provider is a set of async functions with no way to push changes, so reactive collections are read once per query rather than subscribed to.
- Server-generated ids break offline creation. TanStack DB does not remap a local temporary id to a server-assigned one after sync, so offline use requires client-generated ids (UUID, nanoid, ...). The example doesn't have client-generated ids and clearly demonstrates this limit.
- Failed mutation recovery is up to you. Rollback, retry and conflict surfacing are not handled here.
- TanStack DB's API moves fast. This code targets
@tanstack/db0.6.
MIT