Able Pro
NextJS
NextJS
  • ✨Overview
  • 🌴Pre-requisites
  • 🚀Quick Start
  • 📂Folder Structure
  • 🌀State Management
  • 🔒Authentication
  • 📡Axios API Calls
  • 🌐Internationalization
  • 🛠️Project Configuration
  • 🎨Color Presets
  • 🎭Theme/Style Configuration
  • 📚How to
    • Login as First Page
    • Dashboard as First Page
    • Remove menu render from Backend
    • Render Menu from the backend
    • Remove Auth
  • 🖌️Figma
  • 🤝Integration
    • Seed
    • Comparison
  • 📦Dependencies
  • 🗓️Roadmap
  • 🆘Support
  • 📅Changelog
Powered by GitBook
On this page
  • TheseContext API
  • SWR
  • 1. Snackbar

State Management

Managing context, state and hooks

TheseContext 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 - JWT

SWR

SWR is a popular library used for data fetching and state management in React applications. Data fetching is covered in the Axios API calls section, here we are going to cover about state management using SWR.

Mantis is managing the state of the 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 snackbar, it appears in the app. The initial state of snackbar is being captured using useSWR hooks and after that, we are mutating it state based on action calls. Following is the initial state:

src/api/snackbar.ts
const initialState: SnackbarProps = {
  action: false,
  open: false,
  message: 'Note archived',
  anchorOrigin: {
    vertical: 'bottom',
    horizontal: 'right'
  },
  variant: 'default',
  alert: {
    color: 'primary',
    variant: 'filled'
  },
  transition: 'Fade',
  close: false,
  actionButton: false,
  maxStack: 3,
  dense: false,
  iconVariant: 'usedefault'
};

These values have been initialized using useSWR like below:

src/api/snackbar.ts
export function useGetSnackbar() {
  const { data } = useSWR(endpoints.key, () => initialState, {
    revalidateIfStale: false,
    revalidateOnFocus: false,
    revalidateOnReconnect: false
  });

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

  return memoizedValue;
}

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

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

src/components/@extended /Snackbar.tsx
...
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();
  ...
  ...
};

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

src/api/snackbar.ts
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,
        alert: {
          color: alert?.color || initialState.alert.color,
          variant: alert?.variant || initialState.alert.variant
        },
        transition: transition || initialState.transition,
        close: close || initialState.close,
        actionButton: actionButton || initialState.actionButton
      };
    },
    false
  );
}

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

src/views /apps/create.tsx
...
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;

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

src/api/snackbar.js
const initialState = {
  action: false,
  open: false,
  message: 'Note archived',
  anchorOrigin: {
    vertical: 'bottom',
    horizontal: 'right'
  },
  variant: 'default',
  alert: {
    color: 'primary',
    variant: 'filled'
  },
  transition: 'Fade',
  close: false,
  actionButton: false,
  maxStack: 3,
  dense: false,
  iconVariant: 'usedefault'
};

These values have been initialized using useSWR like below:

src/api/snackbar.js
export function useGetSnackbar() {
  const { data } = useSWR(endpoints.key, () => initialState, {
    revalidateIfStale: false,
    revalidateOnFocus: false,
    revalidateOnReconnect: false
  });

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

  return memoizedValue;
}

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

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

src/components/@extended /Snackbar.jsx
...
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();
  ...
  ...
};

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

src/api/snackbar.js
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,
        alert: {
          color: alert?.color || initialState.alert.color,
          variant: alert?.variant || initialState.alert.variant
        },
        transition: transition || initialState.transition,
        close: close || initialState.close,
        actionButton: actionButton || initialState.actionButton
      };
    },
    false
  );
}

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

src/views /apps/create.jsx
...
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;
PreviousFolder StructureNextAuthentication

Last updated 2 months ago

🌀