Zokulko
Zokulko

Reputation: 229

How do I display data from my json file that match my filters

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

Answers (1)

Drew Reese
Drew Reese

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

Edit divine-fire-735rty

Upvotes: 1

Related Questions