Skip to content
Advertisement

REACT- My condition is working partially why?

In my json file from my api, I have a variable apply, If apply:0, Then It should should print my data and If apply:1, Then It should hide my data (i.e row in my Table). Actually when I combine my 2 conditions, It is partially working :(applyStatus ? menus : menus.filter((i) => i.apply !== 1)) && (showGood ? menus : menus.filter((i) => i.taste !== "Good")), i.e Only the ...showGood ?... condition is working and the ...applyStatus?... not working.

Whereas if I do only :

<Table data={matchData && (applyStatus ? menus : menus.filter((i) => i.apply !== 1))> . Then, I have my data where apply:0 are displayed.

What’s wrong in my code please ?

export default function MenuDisplay() {
  const { menuId } = useParams();
  const [selected, setSelected] = useState({});
  const [hidden, setHidden] = useState({});
  const [menus, setMenus]=useState([])
  const [showGood, setShowGood] = useState(false);
  const [applyStatus, setApplyStatus] = useState(false);

  if (menus.apply === 0) {
    setApplyStatus(true)
}
if (menus.apply === 1) {
  setApplyStatus(false)
}

  useEffect (() => {
    axios.post("",{menuId:parseInt(menuId)})
        .then(res => {
            console.log(res)
            setMenus(res.data.menus)
            
        })
        .catch(err => {
            console.log(err)
        })
}, [menuId]);

useEffect (() => {
  const GoodMenus = menus.filter((i) => i.taste === "Good");
  const restOfMenus = menus.filter((i) => i.taste !== "Good");      
  setMenus([...GoodMenus, ...restOfMenus]);
}, [menus]);


  // If any row is selected, the button should be in the Apply state
  // else it should be in the Cancel state
  const buttonMode = Object.values(selected).some((isSelected) => isSelected)
    ? "apply"
    : "cancel";

  const rowSelectHandler = (id) => (checked) => {
    setSelected((selected) => ({
      ...selected,
      [id]: checked
    }));
  };

  const handleClick = () => {
    if (buttonMode === "apply") {
      // Hide currently selected items
      const currentlySelected = {};
      Object.entries(selected).forEach(([id, isSelected]) => {
        if (isSelected) {
          currentlySelected[id] = isSelected;
        }
      });
      setHidden({ ...hidden, ...currentlySelected });

      // Clear all selection
      const newSelected = {};
      Object.keys(selected).forEach((id) => {
        newSelected[id] = false;
      });
      setSelected(newSelected);
    } else {
      // Select all currently hidden items
      const currentlyHidden = {};
      Object.entries(hidden).forEach(([id, isHidden]) => {
        if (isHidden) {
          currentlyHidden[id] = isHidden;
        }
      });
      setSelected({ ...selected, ...currentlyHidden });

      // Clear all hidden items
      const newHidden = {};
      Object.keys(hidden).forEach((id) => {
        newHidden[id] = false;
      });
      setHidden(newHidden);
    }
  };

  const matchData = (
    menus.filter(({ _id }) => {
    return !hidden[_id];
  });

  const getRowProps = (row) => {
    return {
      style: {
        backgroundColor: selected[row.values.id] ? "lightgrey" : "white"
      }
    };
  };

  const data = [
    {
      Header: "id",
      accessor: (row) => row._id
    },
    {
      Header: "Name",
      accessor: (row) => (
        <Link to={{ pathname: `/menu/${menuId}/${row._id}` }}>{row.name}</Link>
      )
    },
    {
      Header: "Description",
      //check current row is in hidden rows or not
      accessor: (row) => row.description
    },
    {
      Header: "Dishes",
      //check current row is in hidden rows or not
      accessor: (row) => row.dishes,
      id: "dishes",
      Cell: ({ value }) => value && Object.values(value[0]).join(", ")
    },
    {
      Header: "Status",
      accessor: (row) => row.status
    },
    {
      Header: "Show",
      accessor: (row) => (
        <Toggle
          value={selected[row._id]}
          onChange={rowSelectHandler(row._id)}
        />
      )
    }
  ];

  const initialState = {
    sortBy: [
      { desc: false, id: "id" },
      { desc: false, id: "description" }
    ],
    hiddenColumns: ["dishes", "id"]
  };

  return (
    <div>
      <button type="button" onClick={handleClick}>
        {buttonMode === "cancel" ? "Cancel" : "Apply"}
      </button>
      show good
      <Toggle value = {showGood} onChange={() => setShowGood(!showGood)} />
      <Table
        data={matchData &&(applyStatus ? menus : menus.filter((i) => i.apply !== 1)) &&
        (showGood ? menus : menus.filter((i) => i.taste !== "Good"))}
        initialState={initialState}
        withCellBorder
        withRowBorder
        withSorting
        withPagination
        rowProps={getRowProps}
      />
    </div>
  );
}

Here my json from my api for menuId:1:

[
  {
    "menuId": 1,
    "_id": "123ml66",
    "name": "Pea Soup",
    "description": "Creamy pea soup topped with melted cheese and sourdough croutons.",
    "dishes": [
      {
        "meat": "N/A",
        "vegetables": "pea"
      }
    ],
    "taste": "Good",
    "comments": "3/4",
    "price": "Low",
    "availability": 0,
    "trust": 1,
    "status": "Pending",
    "apply": 1
  },
  //...other data   

]

Advertisement

Answer

The problem is actually in the usage of your parenthesis. Your current logic looks like this.

(applyStatus ? 
    menus : 
    menus.filter((i) => i.apply !== 1)
) && (showGood ? 
    menus : 
    menus.filter((i) => i.taste !== "Good")
)

If you simplify it it looks like

(Condition ? array : filteredArray) && (Condition ? array : filteredArray)

If you simplify it again it results in

array && array

When you are using && operator on two array like you are doing it will return you the second array which in your case is the array filter on i.taste !== "Good".

I tried to show it with a code sample below

const array = [{price:5, age:10},{price:3, age:8},{price:9, age:12},{price:12, age:13}];

const ageFiltered = array.filter(x => x.age < 11);
const priceFiltered = array.filter(x => x.price > 4);

console.log("Age filtered:" + JSON.stringify(ageFiltered));
console.log("Price filtered:" + JSON.stringify(priceFiltered));

const result = ageFiltered && priceFiltered;
console.log("&& operator:" + JSON.stringify(result));

const doubleFiltered = array.filter(x => x.age < 11 && x.price > 4);
console.log("Dobule filters:" + JSON.stringify(doubleFiltered));

To fix your issue your code must be update to be like this

menus.filter(i => (applyStatus ? true : i.apply !== 1) && (showGood ? true : i.taste !== "Good") )
User contributions licensed under: CC BY-SA
2 People found this is helpful
Advertisement