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") )