Skip to main content

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.

  1. Context Consumption: It retrieves the client from the Archibald Data Context.
  2. Validation: It verifies that the client instance exists.
  3. Direct Access: It returns the full DataClient API, allowing you to manually get, set, delete, or subscribe to 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.