Skip to main content

<DataProvider />

Manages state, providing all context needed to use the hooks. Should be placed as high as possible in application tree as any usage of the hooks is only possible for components below the provider in the React tree.

index.tsx
import { DataProvider } from '@data-client/react';
import { createRoot } from 'react-dom/client';

createRoot(document.body).render(
<DataProvider>
<App />
</DataProvider>,
);

Alternatively integrate state with redux

Props​

interface ProviderProps {
children: ReactNode;
managers?: Manager[];
initialState?: State<unknown>;
Controller?: typeof Controller;
gcPolicy?: GCInterface;
devButton?:
| 'bottom-right'
| 'bottom-left'
| 'top-right'
| 'top-left'
| null;
}

initialState: State<unknown>​

export interface State<T> {
readonly entities: {
readonly [entityKey: string]: { readonly [pk: string]: T } | undefined;
};
readonly endpoints: {
readonly [key: string]: unknown | PK[] | PK | undefined;
};
readonly indexes: NormalizedIndex;
readonly meta: {
readonly [key: string]: {
readonly date: number;
readonly fetchedAt: number;
readonly expiresAt: number;
readonly prevExpiresAt?: number;
readonly error?: ErrorTypes;
readonly invalidated?: boolean;
readonly errorPolicy?: 'hard' | 'soft' | undefined;
};
};
readonly entitiesMeta: {
readonly [entityKey: string]: {
readonly [pk: string]: {
readonly date: number;
readonly expiresAt: number;
readonly fetchedAt: number;
};
};
};
readonly optimistic: (SetResponseAction | OptimisticAction)[];
readonly lastReset: number;
}

Instead of starting with an empty cache, you can provide your own initial state. This can be useful for testing, or rehydrating the cache state when using server side rendering.

managers?: Manager[]​

List of Managers use. This is the main extensibility point of the provider.

getDefaultManagers() can be used to extend the default managers.

Default Production:

[new NetworkManager(), new SubscriptionManager(PollingSubscription)];

Default Development:

[
new DevToolsManager(),
new NetworkManager(),
new SubscriptionManager(PollingSubscription),
];

Controller: typeof Controller​

This allows you to extend Controller to provide additional functionality. This might be useful if you have additional actions you want to dispatch to custom Managers

class MyController extends Controller {
doSomething = () => {
console.log('hi');
};
}

const RealApp = (
<DataProvider Controller={MyController}>
<App />
</DataProvider>
);

gcPolicy?: GCInterface​

Removes data from the store once no component uses it and it has gone stale. Defaults to new GCPolicy().

import { DataProvider, GCPolicy } from '@data-client/react';

const gcPolicy = new GCPolicy({ intervalMS: 60 * 1000 * 10 });

const RealApp = (
<DataProvider gcPolicy={gcPolicy}>
<App />
</DataProvider>
);
GCPolicy options
new GCPolicy({
// how often to sweep (default 5 minutes)
intervalMS: 60 * 1000 * 5,
// how many stale lifetimes before data is removed (default 2)
expiryMultiplier: 2,
// or choose when unused data is removed (replaces expiryMultiplier)
// here: one minute after it goes stale
expiresAt: ({ expiresAt }) => expiresAt + 60 * 1000,
});

devButton​

In development, a small button will appear that gives easy access to browser devtools if installed. This option configures where it shows up, or if null will disable it altogether.

'bottom-right' | 'bottom-left' | 'top-right'| 'top-left' | null = 'bottom-right'

Disable button
<DataProvider devButton={null}>
<App/>
</DataProvider>
Place in top right corner
<DataProvider devButton="top-right">
<App/>
</DataProvider>