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