useDataClient: Low-level access to the Data Cache
Comprehensive Best Practices Guide
Introduction
The useDataClient hook provides direct access to the DataClient instance from the nearest DataProvider. While useFetch and useMutation are the preferred high-level abstractions for most data operations, useDataClient is essential for advanced cache management, manual data invalidation, and side-effects that require direct interaction with the underlying data store.
How it works
useDataClient is a simple React hook that consumes the __DataContext. It ensures that a DataClient is available and throws an invariant error if it's used outside of a DataProvider.
- Context Consumption: It retrieves the
clientfrom the Archibald Data Context. - Validation: It verifies that the client instance exists.
- Direct Access: It returns the full
DataClientAPI, allowing you to manuallyget,set,delete, orsubscribeto cache entries.
Why use useDataClient?
- Manual Cache Invalidation: When you need to clear specific keys or groups after an external event that isn't a standard mutation.
- Optimistic Updates: Manually updating the cache to provide instant UI feedback before a server response is confirmed.
- Cross-Component Synchronization: Subscribing to cache changes for data that is managed elsewhere.
- Prefetching: Initiating data loads outside of the standard component lifecycle.
Recipes
1. Manual Cache Invalidation
Clear a specific key to force a refetch on the next component render.
import { useDataClient } from '@archibald/client';
const MyComponent = () => {
const dataClient = useDataClient();
const handleRefresh = () => {
// Deletes the entry for 'user-profile'
// Any useFetch listening to this key will notice it's gone
dataClient.delete('user-profile');
};
return <button onClick={handleRefresh}>Invalidate Cache</button>;
};
2. Optimistic Update
Update the cache manually to show the new state immediately.
import { useDataClient, useMutation } from '@archibald/client';
const MyComponent = () => {
const dataClient = useDataClient();
const { mutate } = useMutation();
const handleUpdate = async (newName: string) => {
const key = 'user-profile';
// get() returns the cached response payload itself (or null) — not the cache entry
const previousData = dataClient.get(key);
if (!previousData) return;
// 1. Optimistically update the cache
dataClient.set(key, { response: { ...previousData, name: newName }, status: 'done' });
try {
await mutate({ /* ... api call ... */ });
} catch (e) {
// 2. Rollback on error
dataClient.set(key, { response: previousData });
}
};
};
Best Practices
Do: Use for Cross-Cutting Cache Operations
Use useDataClient when you need to interact with data that belongs to a different part of the application or when performing bulk operations like dataClient.clearAll().
Do: Prefer High-Level Hooks for Fetching
Always prefer useFetch for declarative data loading. useDataClient should be used for management, not for primary fetching logic.
Don't: Manually Manage status and response unless necessary
When using dataClient.set(), you are responsible for the structure of the cache entry (which includes response, status, error, etc.). Inconsistent structures can break useFetch expectations.
Don't: Use for Local Component State
If the data is only relevant to a single component or a small tree, use standard React useState. The DataClient is for shared, persistent, and server-synchronized state.