@servicetitan/tanstack-query-mobx
v4.2.1
Published
TanStack Query (React Query) integration for MobX stores with react-ioc dependency injection. Provides declarative data fetching, caching, synchronization, and state management with automatic query deduplication and observable state.
Downloads
7,843
Readme
@servicetitan/tanstack-query-mobx
TanStack Query integration for MobX stores with @servicetitan/react-ioc dependency injection. Provides declarative data fetching, caching, and state management with automatic query deduplication.
Installation
npm install @servicetitan/tanstack-query-mobxQuick Start
1. Provide the Query Client
import { getQueryClient } from '@servicetitan/tanstack-query-mobx';
export const App = provide({
singletons: [getQueryClient()],
})(observer(() => <YourApp />));2. Create a Store
import { QueryApiStore, QueryApiOptions } from '@servicetitan/tanstack-query-mobx';
@injectable()
export class JobsStore extends QueryApiStore<Job[]> {
@inject(JobsApi) private api?: JobsApi;
get queryOptions(): QueryApiOptions<Job[]> {
return {
queryKey: ['jobs'],
queryFn: async () => (await this.api?.getJobs())?.data ?? [],
};
}
}3. Use in Components
const [{ data, isLoading }] = useDependencies(JobsStore);Key Concepts
Query Keys - Arrays that uniquely identify queries. Changes trigger automatic refetch:
queryKey: ['jobs', jobId]; // Refetches when jobId changesObservable State - data, initialized, isLoading, isFetching, isError, error
Stale Time - Default 10 minutes. Set staleTime: 0 for always fresh, Infinity for never stale.
Common Patterns
Mutations (MutationApi reference)
snooze = this.addMutation<void, { id: number }>(() => ({
mutationFn: async arg => (await this.api?.snooze(arg.id))?.data,
invalidatedQueries: [['tasks']], // Refetch after success
}));
await this.snooze.runMutation({ id: 123 });See runMutation() JSDoc for advanced options like custom onSuccess/onError handlers.
Multiple Queries (QueryApiStore reference)
Your primary query should use the queryOptions getter (shown in Quick Start). Use addQuery() only for secondary queries alongside it:
stats = this.addQuery<Stats>(() => ({
queryKey: ['stats'],
queryFn: async () => (await this.api?.getStats())?.data,
}));Use addQuery() in your store to manage multiple independent queries. Each query has its own lifecycle and state.
Shared Clients (Micro-Frontends)
For micro-frontend architectures where multiple app instances need to share query cache, use shared clients at the provider or query level.
Client types:
'page'- Uses reference counting. Disposes when the last component usinggetQueryClient('page')unmounts.'app'- Persists until browser refresh/close. Only available viaglobalClientoption.
See getQueryClient JSDoc for provider-level examples and QueryApiOptions.globalClient JSDoc for query-level examples.
Data-Driven Queries (QueryApiOptions reference)
queryKey: ['logs', jobId], // Auto-refetches when jobId changes
enabled: jobId > 0, // Only runs when condition is trueMobX reactions automatically track queryKey dependencies. When jobId changes, the query refetches.
API Reference
All classes have comprehensive TSDoc comments - use your IDE's intellisense or read the source.
Core Classes
QueryApiStore - Base class for query stores
- Extend this to create stores that fetch and cache data
- Provides observable
data,isLoading,error, andinitializedproperties - Use
addQuery()to add multiple queries andaddMutation()for mutations - See JSDoc for full lifecycle methods
QueryApi - Individual query manager
- Manages a single TanStack Query with MobX integration
- Usually created via
addQuery()in QueryApiStore - Methods:
invalidate(),updateQueryData(),cancel(),refetch() - See JSDoc for lifecycle and state management details
MutationApi - Mutation manager for create/update/delete operations
- Use
runMutation(args, options?)to execute with automatic query invalidation - Provides observable
isPending,isSuccess,isError,errorstate - Configure
invalidatedQueriesto automatically refetch after mutation success - See JSDoc for full configuration options and examples
Configuration Types
QueryApiOptions - Full query configuration extending TanStack Query's QueryObserverOptions
queryKey,queryFn,staleTime,enabled, etc.- Additional:
disposeQuery,autoInitialize,onSuccess,onError,globalClient
MutationApiOptions - Full mutation configuration extending TanStack Query's MutationObserverOptions
mutationFn,onSuccess,onError, etc.- Additional:
invalidatedQueries,globalClient
See TanStack Query docs for core query concepts and all standard options.
Learn More
Source Code & Documentation
All classes, interfaces, and methods have comprehensive TSDoc comments. Explore the source for detailed API documentation:
Core Implementations
- QueryApiStore.ts - Main store base class with
addQuery()andaddMutation() - QueryApi.ts - Query lifecycle, state management, and invalidation
- MutationApi.ts - Mutation operations with automatic invalidation
- getQueryClient.ts - Query client factory with scoping options
Configuration Types
- QueryApiOptions - Complete query configuration interface
- MutationApiOptions - Complete mutation configuration interface
Utilities
- client-helpers.ts - Shared client management for micro-frontends
- QueryClientStore.ts - Query client lifecycle and invalidation helpers
External Resources
- TanStack Query Documentation - Core concepts: queries, mutations, caching, invalidation
- MobX Documentation - Understanding observables and reactions
- @servicetitan/react-ioc - Dependency injection pattern
Testing
import { ContainerBuilder } from '@servicetitan/tanstack-query-mobx/test';
const { container, initialize } = new ContainerBuilder().add(JobsStore).add(JobsApi).build();
jest.spyOn(container.get(JobsApi), 'getJobs').mockResolvedValue({
data: [{ id: 1, title: 'Job' }],
});
await initialize(); // Runs lifecycle + waits for initialized
expect(container.get(JobsStore).data).toHaveLength(1);Testing Utilities
All testing utilities have comprehensive JSDoc comments with examples. Explore the source for detailed API documentation:
ContainerBuilder - Test container builder for dependency injection
- Simplifies setting up stores and dependencies for testing
- Methods:
add(),build(),initialize(),addQueryClient() - Automatically waits for all stores and queries to initialize
waitFor - MobX reaction-based wait helper
- Waits for observable conditions to become true
- Returns promise that resolves when condition is met
SpyBuilder - Abstract base class for mocking API services
- Create mock API services with jest spies
- Methods:
add(),getSpy() - Utilities:
createAxiosResponse(),createAxiosError()
License
Part of the @servicetitan/anvil-uikit-contrib monorepo.
