# \<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.

**Web**

```tsx title="index.tsx"
import { DataProvider } from '@data-client/react';
import { createRoot } from 'react-dom/client';
import App from './App';

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

Alternatively [integrate state with redux](https://dataclient.io/docs/guides/redux.md)

**React Native**

```tsx title="index.tsx"
import { DataProvider } from '@data-client/react';
import { AppRegistry } from 'react-native';
import App from './App';

const Root = () => (
  <DataProvider>
    <App />
  </DataProvider>
);
AppRegistry.registerComponent('MyApp', () => Root);
```

Alternatively [integrate state with redux](https://dataclient.io/docs/guides/redux.md)

**NextJS**

[Full NextJS Guide](https://dataclient.io/docs/guides/ssr.md#nextjs)

```tsx title="app/layout.tsx"
import { DataProvider } from '@data-client/react/nextjs';

export default function RootLayout({ children }) {
  return (
    <html>
      <body>
        <DataProvider>{children}</DataProvider>
      </body>
    </html>
  );
}
```

**Expo**

```tsx title="app/_layout.tsx"
import { Stack } from 'expo-router';
import { DataProvider } from '@data-client/react';

export default function RootLayout() {
  return (
    <DataProvider>
      <Stack>
        <Stack.Screen name="index" />
      </Stack>
    </DataProvider>
  );
}
```

**Anansi**

[Anansi](https://github.com/ntucker/anansi) (beta) is a fully composable framework for React development with optional
Server Side Rendering.

```bash title="bash"
npx @anansi/cli hatch my-project
```

Anansi includes Reactive Data Client automatically.

## Props

```typescript
interface ProviderProps {
  children: ReactNode;
  managers?: Manager[];
  initialState?: State<unknown>;
  Controller?: new (props: { gcPolicy: GCInterface }) => Controller;
  gcPolicy?: GCInterface;
  devButton?:
    | 'bottom-right'
    | 'bottom-left'
    | 'top-right'
    | 'top-left'
    | null;
}
```

### initialState: State\<unknown> {#initialState}

```typescript
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\[] {#managers}

List of [Manager](https://dataclient.io/docs/api/Manager.md)s use. This is the main extensibility point of the provider.

[getDefaultManagers()](https://dataclient.io/docs/api/getDefaultManagers.md) can be used to extend the default managers.

Default Production:

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

Default Development:

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

### Controller?: Controller class {#Controller}

This allows you to extend [Controller](https://dataclient.io/docs/api/Controller.md) to provide additional functionality.
This might be useful if you have additional actions you want to dispatch to custom [Managers](https://dataclient.io/docs/api/Manager.md)

```tsx
import { DataProvider, Controller } from '@data-client/react';
import App from './App';

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

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

### gcPolicy?: GCInterface {#gcPolicy}

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

```tsx
import { DataProvider, GCPolicy } from '@data-client/react';
import App from './App';

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

const RealApp = (
  <DataProvider gcPolicy={gcPolicy}>
    <App />
  </DataProvider>
);
```

```ts title="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](https://dataclient.io/docs/getting-started/debugging.md) 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'`

```tsx title="Disable button"
import { DataProvider } from '@data-client/react';
import App from './App';

<DataProvider devButton={null}>
  <App/>
</DataProvider>
```

```tsx title="Place in top right corner"
import { DataProvider } from '@data-client/react';
import App from './App';

<DataProvider devButton="top-right">
  <App/>
</DataProvider>
```
