Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How to output the values of an object in an array if one of the object's values matches a value in a different array – React?

If I have this array:

const data = [
    {
      id: 1,
      category: "ladders",
      name: "N/A",
      price: 0,
    },
    {
      id: 2,
      category: "ladders",
      name: "Ladder 1",
      price: 220,
    },
    {
      id: 3,
      category: "ladders",
      name: "Ladder 2",
      price: 420,
    },
    {
      id: 4,
      category: "ladders",
      name: "Ladder 3",
      price: 515,
    },
]

And I have this in my useState hook:

  const [selections, setSelections] = useState({
    ladders: [2, 4]
  });

I’m trying to output in my JSX the values of the objects in data that have a matching ‘id’ to the values in my ‘ladders’ property in my useState hook (i.e. 2 and 4). I can do it by manually specifying the array indexes, like so:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

{data
  .filter((item) => item.id === selections.ladders[0])
  .map((item) => {
    return (
      <li className="item" key={item.id}>
        <div className="item__body">
          <h3 className="item__name">{item.name}</h3>
        </div>
        <span className="item__price">£{item.price}</span>
      </li>
    );
  })}

{data
  .filter((item) => item.id === selections.ladders[1])
  .map((item) => {
    return (
      <li className="item" key={item.id}>
        <div className="item__body">
          <h3 className="item__name">{item.name}</h3>
        </div>
        <span className="item__price">£{item.price}</span>
      </li>
    );
  })}

But how I can refactor this so I don’t have to manually specify the ‘ladders’ array indexes? Any help appreciated.

>Solution :

You can use Array.prototype.includes.

{data
  .filter((item) => selections.ladders.includes(item.id))
  .map((item) => {
    return (
      <li className="item" key={item.id}>
        <div className="item__body">
          <h3 className="item__name">{item.name}</h3>
        </div>
        <span className="item__price">£{item.price}</span>
      </li>
    );
  })}

If you can change the structure of data, you can actually change it to an object for a bit more performance.

{
    "1": {
        "id": 1,
        "category": "ladders",
        "name": "N/A",
        "price": 0
    },
    "2": {
        "id": 2,
        "category": "ladders",
        "name": "Ladder 1",
        "price": 220
    },
    "3": {
        "id": 3,
        "category": "ladders",
        "name": "Ladder 2",
        "price": 420
    },
    "4": {
        "id": 4,
        "category": "ladders",
        "name": "Ladder 3",
        "price": 515
    }
}

Then you can do setSelected(prev=>[...prev, item.id]). And for rendering:

{selected
  .map((id) => {
    return (
      <li className="item" key={id}>
        <div className="item__body">
          <h3 className="item__name">{data[id].name}</h3>
        </div>
        <span className="item__price">£{data[id].price}</span>
      </li>
    );
  })}

If you don’t have access to data, you can use a Set. Checking if an element is in a set is O(1) as compared to O(n) for Array.includes.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading