# State Management

## Context API

Context provides a way to pass data through the component tree without having to pass props down manually at every level.

We are using context for login methods - **`Auth0, JWT, Firebase, Supabase, AWS.`**

### SWR <a href="#swr" id="swr"></a>

SWR is a popular library for data fetching and state management in React applications. Data fetching is covered in the [Axios API calls](/able-pro/react/axios-api-calls.md) section. Here, we are going to cover state management using SWR.

Mantis is managing the state of following using SWR

1. Snackbar states
2. Menu states
3. E-commerce Cart

## 1. Snackbar

Snackbar is used to show notifications in the application. Whenever a component dispatches an action with data to show a snackbar, it appears in the app. The initial state of the snackbar is being captured using useSWR hooks, and after that, we are mutating its state based on action calls. The following is the initial state:

{% tabs %}
{% tab title="VITE(TS)" %}
{% code title="src/api/snackbar.ts" %}

```typescript
const initialState: SnackbarProps = {
  action: false,
  open: false,
  message: 'Note archived',
  anchorOrigin: {
    vertical: 'bottom',
    horizontal: 'right'
  },
  severity: 'success',
  variant: 'default',
  alert: {
    variant: 'filled'
  },
  transition: 'Fade',
  close: false,
  actionButton: false,
  maxStack: 3,
  dense: false,
  iconVariant: 'usedefault'
};
```

{% endcode %}
{% endtab %}

{% tab title="VITE(JS)" %}
{% code title="src/api/snackbar.js" %}

```javascript
const initialState = {
  action: false,
  open: false,
  message: 'Note archived',
  anchorOrigin: {
    vertical: 'bottom',
    horizontal: 'right'
  },
  severity: 'success',
  variant: 'default',
  alert: {
    variant: 'filled'
  },
  transition: 'Fade',
  close: false,
  actionButton: false,
  maxStack: 3,
  dense: false,
  iconVariant: 'usedefault'
};
```

{% endcode %}
{% endtab %}
{% endtabs %}

These values have been initialised using useSWR like below:

{% tabs %}
{% tab title="VITE(TS)" %}
{% code title="src/api/snackbar.ts" %}

```typescript
export function useGetSnackbar() {
  const { data } = useSWR(endpoints.key, () => initialState, {
    revalidateIfStale: false,
    revalidateOnFocus: false,
    revalidateOnReconnect: false
  });

  const memoizedValue = useMemo(() => ({ snackbar: data! }), [data]);

  return memoizedValue;
}
```

{% endcode %}
{% endtab %}

{% tab title="VITE(JS)" %}
{% code title="src/api/snackbar.js" %}

```javascript
export function useGetSnackbar() {
  const { data } = useSWR(endpoints.key, () => initialState, {
    revalidateIfStale: false,
    revalidateOnFocus: false,
    revalidateOnReconnect: false
  });

  const memoizedValue = useMemo(() => ({ snackbar: data! }), [data]);

  return memoizedValue;
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

Now, how to read these values and update them as well.

To read the values and listen, following the SWR hooks is sufficient in the component. Whenever any changes happen, it is activated like a redux selector and acts based on logic.

{% tabs %}
{% tab title="VITE(TS)" %}
{% code title="src/components/@extended /Snackbar.tsx" %}

```typescript
...
import { closeSnackbar, useGetSnackbar } from 'api/snackbar';
...

// animation options
const animation: KeyedObject = {
  SlideLeft: TransitionSlideLeft,
  SlideUp: TransitionSlideUp,
  SlideRight: TransitionSlideRight,
  SlideDown: TransitionSlideDown,
  Grow: GrowTransition,
  Fade
};

// ==============================|| SNACKBAR ||============================== //

export default function Snackbar() {
  const { snackbar } = useGetSnackbar();
  ...
  ...
};
```

{% endcode %}
{% endtab %}

{% tab title="VITE(JS)" %}
{% code title="src/components/@extended /Snackbar.jsx" %}

```javascript
...
import { closeSnackbar, useGetSnackbar } from 'api/snackbar';
...

// animation options
const animation = {
  SlideLeft: TransitionSlideLeft,
  SlideUp: TransitionSlideUp,
  SlideRight: TransitionSlideRight,
  SlideDown: TransitionSlideDown,
  Grow: GrowTransition,
  Fade
};

// ==============================|| SNACKBAR ||============================== //

export default function Snackbar() {
  const { snackbar } = useGetSnackbar();
  ...
  ...
};
```

{% endcode %}
{% endtab %}
{% endtabs %}

To open the Snack bar, we need to change the value and mutate the state. Here is how it is done

{% tabs %}
{% tab title="VITE(TS)" %}
{% code title="src/api/snackbar.ts" %}

```typescript
export function openSnackbar(snackbar: SnackbarProps) {
  // to update local state based on key

  const { action, open, message, anchorOrigin, variant, alert, transition, close, actionButton } = snackbar;

  mutate(
    endpoints.key,
    (currentSnackbar: any) => {
      return {
        ...currentSnackbar,
        action: action || initialState.action,
        open: open || initialState.open,
        message: message || initialState.message,
        anchorOrigin: anchorOrigin || initialState.anchorOrigin,
        variant: variant || initialState.variant,
        severity: severity || initialState.severity,
        alert: { variant: alert?.variant || initialState.alert.variant },
        transition: transition || initialState.transition,
        close: close || initialState.close,
        actionButton: actionButton || initialState.actionButton
      };
    },
    false
  );
}
```

{% endcode %}
{% endtab %}

{% tab title="VITE(JS)" %}
{% code title="src/api/snackbar.js" %}

```javascript
export function openSnackbar(snackbar) {
  // to update local state based on key

  const { action, open, message, anchorOrigin, variant, alert, transition, close, actionButton } = snackbar;

  mutate(
    endpoints.key,
    (currentSnackbar) => {
      return {
        ...currentSnackbar,
        action: action || initialState.action,
        open: open || initialState.open,
        message: message || initialState.message,
        anchorOrigin: anchorOrigin || initialState.anchorOrigin,
        variant: variant || initialState.variant,
       severity: severity || initialState.severity,
        alert: { variant: alert?.variant || initialState.alert.variant },
        transition: transition || initialState.transition,
        close: close || initialState.close,
        actionButton: actionButton || initialState.actionButton
      };
    },
    false
  );
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

Then the method *openSnackbar* will be called from components to open the snackbar.

{% tabs %}
{% tab title="VITE  (TS)" %}
{% code title="src/pages/apps/invoice /create.tsx" %}

```typescript
...
import { openSnackbar } from 'api/snackbar';
// types
import { SnackbarProps } from 'types/snackbar';
...

// ==============================|| INVOICE - CREATE ||============================== //

const Create = () => {
  ...
  const handlerCreate = (values: any) => {
    const newList: InvoiceList = {
      ...
    };
    ...
    openSnackbar({
      open: true,
      message: 'Invoice Added successfully',
      anchorOrigin: { vertical: 'top', horizontal: 'right' },
      variant: 'alert',
      alert: {
        color: 'success'
      }
    } as SnackbarProps);
    ...
  };



  return (
    <MainCard>
      ...
    </MainCard>
  );
};

export default Create;
```

{% endcode %}
{% endtab %}

{% tab title="VITE (JS)" %}
{% code title="src/pages/apps/invoice /create.jsx" %}

```javascript
...
import { openSnackbar } from 'api/snackbar';

...

// ==============================|| INVOICE - CREATE ||============================== //

const Create = () => {
  ...
  const handlerCreate = (values) => {
    const newList: InvoiceList = {
      ...
    };
    ...
    openSnackbar({
      open: true,
      message: 'Invoice Added successfully',
      anchorOrigin: { vertical: 'top', horizontal: 'right' },
      variant: 'alert',
      alert: {
        color: 'success'
      }
    });
    ...
  };



  return (
    <MainCard>
      ...
    </MainCard>
  );
};

export default Create;
```

{% endcode %}
{% endtab %}
{% endtabs %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://phoenixcoded.gitbook.io/able-pro/react/state-management.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
