Getting started
Fetchium is a reactive data-fetching library built on Signalium. It gives you class-based query definitions, automatic entity normalization and caching, a type DSL for describing API shapes, and first-class React integration --- all driven by Signalium's fine-grained reactivity engine.
With Fetchium you define your API surface as plain classes. The library handles fetch deduplication, caching, staleness, background refetching, offline support, and entity identity so your components stay simple and your data stays consistent.
Quick Start Guide
1. Install the packages
# Using npm
npm install fetchium signalium
# Using yarn
yarn add fetchium signalium
# Using pnpm
pnpm add fetchium signalium
2. Setup the Babel transform
Signalium requires a Babel transform to enable async reactivity. Add it to your bundler config so that async dependency tracking works correctly.
Vite + React
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import { signaliumPreset } from 'signalium/transform';
export default defineConfig({
plugins: [
react({
babel: {
presets: [signaliumPreset()],
},
}),
],
});
babel.config.js
import { signaliumPreset } from 'signalium/transform';
module.exports = {
presets: [
'@babel/preset-env',
'@babel/preset-react',
'@babel/preset-typescript',
signaliumPreset(),
],
};
3. Create a QueryClient and wrap your app
Every Fetchium app needs a QueryClient backed by a store. The client manages query instances, the entity cache, and network state. Wrap your component tree in a ContextProvider so that queries can find the client.
import { QueryClient, QueryClientContext } from 'fetchium';
import { ContextProvider } from 'signalium/react';
const client = new QueryClient();
function App() {
return (
<ContextProvider contexts={[[QueryClientContext, client]]}>
<YourApp />
</ContextProvider>
);
}
This is the minimal setup. The store defaults to an in-memory cache and RESTQueryAdapter is auto-instantiated on first use with globalThis.fetch. When you need a baseUrl, auth headers, or persistent storage, pass explicit options --- see Project Setup.
Want to go deeper?
For a complete guide to configuring baseUrl, auth headers, persistent stores, and project structure, see Project Setup.
4. Define an Entity and a Query
Entities describe the shape of your API resources. Queries describe how to fetch them. Both use the t type DSL for field definitions.
import { t, Entity } from 'fetchium';
import { RESTQuery } from 'fetchium/rest';
class User extends Entity {
__typename = t.typename('User');
id = t.id;
name = t.string;
email = t.string;
}
class GetUser extends RESTQuery {
params = { id: t.number };
path = `/users/${this.params.id}`;
result = { user: t.entity(User) };
}
t.typename and t.id identify the entity for normalization and deduplication. path uses template literal interpolation with this.params to embed parameter values. t.entity(User) tells Fetchium to parse and normalize the response as a User entity.
5. Use the query in a component
import { useQuery } from 'fetchium/react';
function UserProfile({ userId }: { userId: number }) {
const result = useQuery(GetUser, { id: userId });
if (!result.isReady) return <div>Loading...</div>;
if (result.isRejected) return <div>Error: {result.error.message}</div>;
return (
<div>
<h1>{result.value.user.name}</h1>
<p>{result.value.user.email}</p>
</div>
);
}
Both approaches return a ReactivePromise with properties like value, error, isPending, isReady, isResolved, and isRejected. The component re-renders automatically when the query state changes.
Next Steps
Project Setup
Configure baseUrl, auth, stores, and project structure for production
Queries
Deep dive into query definitions, the template system, and usage patterns
Entities
Understand normalized entity caching and identity-stable proxies
Auth & Headers
Add authentication tokens and custom headers to your requests