Rishav Sinha
Rishav Sinha

Reputation: 359

Conditional rendering inside a map function

I have a list of buttons in a array

  const menuItems = [
      {
        key: "delete",
        title: "Delete Order",
        showFor: "all",
      },
      {
        key: "cancel",
        title: "Cancel Order",

        showFor: "all",
      },
      {
        key: "confirm",
        title: "Confirm Order",

        showFor: "unconfirmed",
      },
    ];

Now what i want to render it conditionally,for example i will check if the current state of the component and then render it accordingly. For example in confirmed order want to show only the delete and cancel not the confirm one. But for unconfirmed order i want to show all them of them.

Currently i am doing like this

   {currentTable === "notconfirmed"
          ? menuItems.map((item) => {
              return (
                <Menu.Item key={item.key}>
                    <div>{item.title}</div>
                  </div>
                </Menu.Item>
              );
            })
          : menuItems
              .filter((item) => item.showFor != "unconfirmed")
              .map((kk) => {
                return (
                  <Menu.Item key={kk.key}>
                    <div>
                      <div>{kk.title}</div>
                    </div>
                  </Menu.Item>
                );
              })}

It is working fine but this looks really messy any clean way of doing this?

Upvotes: 0

Views: 303

Answers (3)

Leandro William
Leandro William

Reputation: 467

I think that you need to refact the data... It's not a good idea to have the filter logic in the data... The property showFor seems like Code Smell

But there is an example to improve your code.

If you wanna keep your filter function, you use something like:

const component = (menuItems, currentTable = "notconfirmed") => {
    const filterValue = currentTable === "notconfirmed" 
    
    return <>
        {menuItems.filter((item) => filterValue ? item.showFor === "unconfirmed" : item.showFor !== "unconfirmed").map((filterdItem) => (
            <Menu.Item key={filterdItem.key}>
                <div>
                    <div>{filterdItem.title}</div>
                </div>
            </Menu.Item>
        ))}
    </>
}

In order to avoid the filter to make less operations and optimize your code, it's a better option:

const component = (menuItems, currentTable = "notconfirmed") => {
    const filterValue = currentTable === "notconfirmed" ? "all" : "unconfirmed"
    
    return <>
        {menuItems.map((filterdItem) =>
        (
            filterdItem === filterValue && <Menu.Item key={filterdItem.key}>
                <div>
                    <div>{filterdItem.title}</div>
                </div>
            </Menu.Item>
        ))}
    </>
}

Upvotes: 0

Viet
Viet

Reputation: 12807

You can add conđition in map like this:

{menuItems.map((item) => {
      if (
        currentTable !== "notconfirmed" &&
        item.showFor === "unconfirmed"
      ) {
        return null;
      }
      return (
        <Menu.Item key={item.key}>
          <div>{item.title}</div>
        </Menu.Item>
      );
    })}

Upvotes: 1

Ayzrian
Ayzrian

Reputation: 2465

Well that is the way it done.

You can refactor your code moving the render logic of each block into a function or a component to make it more clean.

Upvotes: 0

Related Questions