Home > Software engineering >  Show and Hide Condition in React
Show and Hide Condition in React

Time:06-12

I have a simple problem here which I can't figure out. I wanted to hide menus depending on the condition.

For example if status contains at least one "Unlinked". "All unlinked images" menu should appear. I did used .some and I wonder why it doesn't return a boolean.

Codesandbox is here Click here

  const showDeleteAllInvalidButton = () => {
    const productImages = products?.flatMap((product) =>
      product.productImages.filter((image) => image?.status)
    );

    return productImages?.some((e) => e?.status === "Invalid");
  };

  const showDeleteAllUnlinkedButton = () => {
    const productImages = products?.flatMap((product) =>
      product.productImages.filter((image) => image?.status)
    );

    return productImages?.some((e) => e?.status === "Unlinked");
  };

CodePudding user response:

The methods do return a boolean. But in the menus array you are assigning a function reference not the result -

show: showDeleteAllInvalidButton // function reference

show is now assigned a reference to the function showDeleteAllInvalidButton not the result of productImages?.some. You need to invoke the functions when assigning -

show: showDeleteAllInvalidButton() // result of productImages?.some

CodePudding user response:

In your menus object you have a key that contains a function, so if you want this function to filter out your elements you need to execute the show method in side the filter method.

import React, { useState } from "react";
import Button from "@mui/material/Button";
import MenuItem from "@mui/material/MenuItem";
import KeyboardArrowDownIcon from "@mui/icons-material/KeyboardArrowDown";
import CustomMenu from "../../Menu";

const products = [
  {
    productName: "Apple",
    productImages: [
      {
        status: "Unlinked"
      }
    ]
  },
  {
    productName: "Banana",
    productImages: [
      {
        status: "Unlinked"
      }
    ]
  },
  {
    productName: "Mango",
    productImages: [
      {
        status: "Unlinked"
      },
      {
        status: "Unlinked"
      }
    ]
  }
];

const HeaderButtons = () => {
  const [anchorEl, setAnchorEl] = useState(null);
  const open = Boolean(anchorEl);

  const handleClick = (event) => {
    setAnchorEl(event.currentTarget);
  };

  const handleClose = () => {
    setAnchorEl(null);
  };

  const showDeleteAllInvalidButton = () => {
    const productImages = products?.flatMap((product) =>
      product.productImages.filter((image) => image?.status)
    );

    return productImages?.some((e) => e?.status === "Invalid");
  };

  const showDeleteAllUnlinkedButton = () => {
    const productImages = products?.flatMap((product) =>
      product.productImages.filter((image) => image?.status)
    );

    return productImages?.some((e) => e?.status === "Unlinked");
  };

  const menus = [
    {
      id: 1,
      name: "Invalid images",
      action: () => {
        handleClose();
      },
      show: showDeleteAllInvalidButton
    },
    {
      id: 2,
      name: "Unlinked images",
      action: () => {
        handleClose();
      },
      show: showDeleteAllUnlinkedButton
    },
    {
      id: 3,
      name: "All images",
      action: () => {
        handleClose();
      },
      show: () => true // not that I changed it to a function for consistency, but you can check for type in the filter method instead of running afunction
    }
  ];

  return (
    <div>
      <Button
        color="error"
        aria-haspopup="true"
        aria-expanded={open ? "true" : undefined}
        variant="outlined"
        onClick={handleClick}
        endIcon={<KeyboardArrowDownIcon />}
      >
        Options
      </Button>
      <CustomMenu anchorEl={anchorEl} open={open} onClose={handleClose}>
        {menus
          .filter((e) => e.show()) // here is your mistake
          .map(
            ({
              id = "",
              action = () => {},
              icon = null,
              name = "",
              divider = null
            }) => (
              <>
                <MenuItem key={id} onClick={action} disableRipple>
                  {icon}
                  {name}
                </MenuItem>
                {divider}
              </>
            )
          )}
      </CustomMenu>
    </div>
  );
};

export default HeaderButtons;

In your code, it will always render because your filter functions are evaluating as truth.

  • Related