Search code examples
javascriptreactjsreact-bootstrap

Using react-bootstrap Alert in map not working


I am trying to use the Alert component in react-boostrap using a map in the same way the do in this guide. I want to have this list as a component so that I can use it in several places. For this, I created an interface that looks like this:

import { ReactElement } from "react";
import { Variant } from "react-bootstrap/types";

export interface AlertItem {
    content: string | ReactElement;
    index: number;
    variant?: Variant
    header?: string;
}

In the components where I want to be able to display alerts as a list, I (dynamically) create an AlertItem[] array and a function that removes the AlertItem at index "i". I then try to display the list of alerts using <AlertList alerts={alerts} closeAlertCallback={closeAlert} />.

So my AlertList looks like this:

import { ReactElement } from "react";
import { Alert } from "react-bootstrap";
import { AlertItem } from "../interfaces/AlertItem";

interface Props {
    alerts: AlertItem[];
    closeAlertCallback: (index: number) => void;
}

const AlertList = ({alerts, closeAlertCallback}: Props): ReactElement => {
    if (alerts.length === 0) {
        return <></>;
    }

    return (
        <>
            {alerts.map((alert, i) => {
                <Alert key={`alert-${i}`} variant={alert.variant} onClose={() => closeAlertCallback(i)} dismissible>
                    {alert.header && <Alert.Heading>{alert.header}</Alert.Heading>}
                    {alert.content}
                </Alert>
            })}
        </>
    );
};

export default AlertList;

My problem is that this does not render at all. If I instead remove the map and always only render (and remove) the first item in the array, it renders that item just fine. The return then looks like this:

    return (
        <>
            <Alert variant={alerts[0].variant} onClose={() => closeAlertCallback(0)} dismissible>
                {alerts[0].header && <Alert.Heading>{alerts[0].header}</Alert.Heading>}
                {alerts[0].content}
            </Alert>
        </>
    );

Note that it is the only change in the file. The incoming alerts array and the closeAlertCallback is exactly the same. I can even remove the first alert in the array by clicking the X, which then renders the next alert.

I am at a total loss about what I'm doing wrong. I'm probably missing something obvious, or is just a bit blind and don't see the error.

Can someone else spot my mistake?


Solution

  • I think you are missing the 'return' inside the map function

    return (
            <>
                {alerts.map((alert, i) => { return
                    <Alert key={`alert-${i}`} variant={alert.variant} onClose={() => closeAlertCallback(i)} dismissible>
                        {alert.header && <Alert.Heading>{alert.header}</Alert.Heading>}
                        {alert.content}
                    </Alert>
                })}
            </>
        );