# LogoutManager

Logs out based on fetch responses. By default this is triggered by [401 (Unauthorized)](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/401) status responses.

> **Info: implements**
>
> `LogoutManager` implements [Manager](https://dataclient.io/docs/api/Manager.md)

## Usage

**Web**

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

const managers = [new LogoutManager(), ...getDefaultManagers()];

createRoot(document.body).render(
  <DataProvider managers={managers}>
    <App />
  </DataProvider>,
);
```

**React Native**

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

const managers = [new LogoutManager(), ...getDefaultManagers()];

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

**NextJS**

```tsx title="app/Provider.tsx"
'use client';
import { LogoutManager, getDefaultManagers } from '@data-client/react';
import { DataProvider } from '@data-client/react/nextjs';

const managers = [new LogoutManager(), ...getDefaultManagers()];

export default function Provider({
  children,
}: {
  children: React.ReactNode;
}) {
  return <DataProvider managers={managers}>{children}</DataProvider>;
}
```

```tsx title="app/layout.tsx"
import Provider from './Provider';

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

**Expo**

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

const managers = [new LogoutManager(), ...getDefaultManagers()];

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

### Custom logout handler

```ts
import { unAuth } from '../authentication';

const managers = [
  new LogoutManager({
    handleLogout(controller) {
      // call custom unAuth function we defined
      unAuth();
      // still reset the store
      controller.resetEntireStore();
    },
  }),
  ...getDefaultManagers(),
];
```

> **Tip**
>
> Use [controller.invalidateAll](https://dataclient.io/docs/api/Controller.md#invalidateAll) to only clear part of the cache.
>
> ```ts
> import { unAuth } from '../authentication';
>
> const myDomain = 'http://test.com';
> const testKey = (key: string) => key.startsWith(`GET ${myDomain}`);
>
> const managers = [
>   new LogoutManager({
>     handleLogout(controller) {
>       // call custom unAuth function we defined
>       unAuth();
>       // still reset the store
>       controller.invalidateAll({ testKey });
>     },
>   }),
>   ...getDefaultManagers(),
> ];
> ```

## Members

### handleLogout(controller)

By default simply calls [controller.resetEntireStore()](https://dataclient.io/docs/api/Controller.md#resetEntireStore)

This should be sufficient if login state is determined by a user entity existence in the Reactive Data Client store. However,
you can override this method via inheritance if more should be done.

### shouldLogout(error)

```ts
protected shouldLogout(error: UnknownError) {
  // 401 indicates reauthorization is needed
  return error.status === 401;
}
```

## Github Example

Example app: [github-app](https://github.com/reactive/data-client/tree/master/examples/github-app) ([`src/RootProvider.tsx`](https://github.com/reactive/data-client/blob/master/examples/github-app/src/RootProvider.tsx))
