Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to dynamically create multiple alerts inside mui v5 Snackbar

I am calling an API to do few actions.
I want to take the response of each action and show it inside Snackbar/alert.

I am able to show only the first response and nothing else even after iterating the messages in a map.

Here is my business logic calling the api

try {
      const deletedUser = await deleteUser({ username: username });
      [deletedUser.data.status.action1, deletedUser.data.status.action2].map(
        (msg) =>
          setNotify({
            isOpen: true,
            message: msg,
            type: "success",
          })
      );
    } catch (error) {}

setNotify will open the Snackbar with the alerts

import React from "react";
import { Snackbar, Alert } from "@mui/material";

import { styled } from "@mui/material/styles";

const StyledSnackbar = styled((props) => <Snackbar {...props} />)(
  ({ theme }) => ({
    "& .MuiSnackbar-root": {
      top: theme.spacing(15),
    },
  })
);

export default function Notification(props) {
  const { notify, setNotify } = props;
  const handleClose = (event, reason) => {
    setNotify({
      ...notify,
      isOpen: false,
    });
  };
  return (
    <StyledSnackbar
      open={notify.isOpen}
      autoHideDuration={10000}
      anchorOrigin={{ vertical: "top", horizontal: "right" }}
      onClose={handleClose}
    >
      <Alert severity={notify.type} onClose={handleClose}>
        {notify.message}
      </Alert>
    </StyledSnackbar>
  );
}

The only issue it's only displaying the first action and nothing else.

Edit On Sandbox

I suspect the alerts are overlapping on top of each other Maybe we need to add some sort of AutoGrow prop

like image 381
Moe Avatar asked Sep 06 '25 02:09

Moe


1 Answers

You have to use notistack as described in the MUI doc:

This example demonstrates how to use notistack. notistack has an imperative API that makes it easy to display snackbars, without having to handle their open/close state. It also enables you to stack them on top of one another (although this is discouraged by the Material Design guidelines).

Start by wrapping your app inside a SnackbarProvider component then use useSnackbar hook to access enqueueSnackbar in order to add a snackbar to the queue to be displayed:

App.js

import "./styles.css";
import React from "react";
import { SnackbarProvider } from "notistack";
import Notification from "./Notification";

export default function App() {
  return (
    <SnackbarProvider maxSnack={3}>
      <div className="App">
        <h1>Dynamic Snackbar Alerts</h1>
        <Notification />
      </div>
    </SnackbarProvider>
  );
}

Notification.js

import React from "react";
import { Button } from "@mui/material";
import { useSnackbar } from "notistack";

export default function Notification(props) {
  const { enqueueSnackbar } = useSnackbar();

  const handleClick = async () => {
    try {
      const deletedUser = await deleteUser({ username: username });
      [deletedUser.data.status.action1, deletedUser.data.status.action2].forEach((msg) => {
          enqueueSnackbar(msg, {
            variant: "success",
            autoHideDuration: 10000,
            anchorOrigin: { vertical: "top", horizontal: "right" }
          });
      });
    } catch (error) {}
  };

  return (
    <Button variant="outlined" onClick={handleClick}>
      Generate Snackbar Dynamicly
    </Button>
  );
}

Demo:

Edit sparkling-moon-ikm0o

like image 126
Fraction Avatar answered Sep 08 '25 15:09

Fraction