Reputation: 229
I'm creating a multi steps form in React and I want a page (Filters.jsx) in my form, that returns me all the menus name (contained in data.json) that matches my filters ( beaf, chicken, vegetables), but I don't kow how to do that.
import React from "react";
export default function Filter() {
return (
<div className="flex flex-col">
<div className=" w-full mx-2 flex-1">
<div className="font-bold h-6 mt-3 text-gray-600 leading-8 uppercase ">
{" "}
Norms
</div>
<tbody className="bg-white my-2 p-1 flex borer border-gray-200 rounded text-gray-500">
<tr>
<td className="font-bold h-8 mt-5 leading-8 uppercase ">
<td>
<input type="checkbox" value="beaf" className="w-8 h-3" /> beaf
</td>
<td>
<input type="checkbox" value="chicken" className="w-8 h-3" />
chicken
</td>
<td>
<input type="checkbox" value="vegetables" className="w-8 h-3" />
vegetables
</td>
</td>
</tr>
</tbody>
</div>
</div>
);
}
Here is the link of my sandbox ( browse /menu/form to see the form): https://codesandbox.io/s/unruffled-river-ktoic8?
What I tried:
export default function Filters() {
//Filters events
const ref = [
{ name: "beaf" },
{ name: "chicken" },
{ name: "vegetables" }
]
const [norms, setNorms] = useState([]);
useEffect(() => {
setNorms(ref);
}, []);
const handleChange = (e) => {
const { name, checked } = e.target;
let tempR = norms.map((r) =>
r.name === name ? { ...r, isChecked: checked } : r
);
setNorms(tempR);
}
return (
<div>
<form className="form w-100">
{
norms.map((e, index) => (
<div className="form-check" key={index}>
<input
type="checkbox"
className="form-check-input"
name={e.name}
checked={e?.isChecked || false}
onChange={handleChange}
/>
<label className="form-check-label ms-2">{e.name}</label>
</div>
))
}
</form >
</div>
)
Upvotes: 1
Views: 290
Reputation: 202836
I suggest using an object or Map to hold the filter values where the filter name is the key and the checked value is the value.
const [filters, setFilters] = React.useState({});
Create a handler that sets the checked value for a specific input by name.
const changeHandler = (e) => {
const { name, checked } = e.target;
setFilters((filters) => ({
...filters,
[name]: checked
}));
};
Render the inputs and set the checked
prop from state.
{["beef", "chicken", "vegetables"].map((name) => (
<td key={name}>
<label>
<input
type="checkbox"
checked={filters[name]}
onChange={changeHandler}
name={name}
className="w-8 h-3"
/>
{name}
</label>
</td>
))}
And then filter/map the data, all inline.
import data from "../../data.json";
...
{data
.filter((item) => {
// get array of enabled filter keys
const filterEntries = Object.entries(filters)
.filter(([, value]) => Boolean(value))
.map(([key]) => key);
// some filter enabled
if (filterEntries.length) {
// check proteins
if (filters.beef || filters.chicken) {
return item.dishes.some((dish) =>
filterEntries.includes(dish.meat)
);
}
// check vegetables
if (filters.vegetables) {
return item.dishes.some((dish) => !!dish.vegetables);
}
}
// no filter enabled, return all elements
return true;
})
.map((item) => (
<tr key={item.id}>
.... map data item properties here ...
</tr>
))}
Upvotes: 1