Need to find object from an array with two objects

Welcome to Programming Tutorial official website. Today - we are going to cover how to solve / find the solution of this error Need to find object from an array with two objects on this date .

I am trying to find an object from an array of objects. I am using NextJs, React 17.0.2, typescript 4.5.4, framer-motion and tailwindcss.

Here’s the array:

// rolls.js
const Rolls = [
  {
    titulo: "MERV 8",
    rolls: [
      {
        medida: 16,
        existencia: 15,
        id: "MERV816"
      },
      {
        medida: 20,
        existencia: 25,
        id: "MERV820"
      },
      {
        medida: 24,
        existencia: 12,
        id: "MERV824"
      },
      {
        medida: 25,
        existencia: 10,
        id: "MERV825"
      }
    ]
  },
  {
    titulo: "MERV 13",
    rolls: [
      {
        medida: 16,
        existencia: 15,
        id: "MERV1316"
      },
      {
        medida: 20,
        existencia: 25,
        id: "MERV1320"
      },
      {
        medida: 24,
        existencia: 12,
        id: "MERV1324"
      },
      {
        medida: 25,
        existencia: 10,
        id: "MERV1325"
      }
    ]
  }
];

export default Rolls;

And here is the component:

// app.tsx
import "./styles.css";
import { useState } from "react";
import PageTitle from "./PageTitle";
import Rolls from "./rolls";

export default function App() {
  const [selectedRoll, setSelectedRoll] = useState("none");
  const [quantity, setQuantity] = useState(0);

  const decreaseQuantity = () => {
    if (quantity > 0) {
      setQuantity(quantity - 1);
    }
  };

  const increaseQuantity = () => {
    if (quantity < 10) {
      setQuantity(quantity + 1);
    }
  };

  const selectARoll = (e: any) => {
    e.preventDefault();
    setSelectedRoll(e.target.value);
  };

  return (
    <main className={"p-4 font-mono"}>
      <PageTitle title="Producción" />

      <h2 className={"text-orange-400 font-bold text-2xl"}>Inventario</h2>
      {Rolls.map((v, i) => {
        return (
          <section key={i} className="grid gap-4 md:grid-cols-6">
            <h2 className="font-bold text-xl pt-4 md:col-span-6">
              Eficiencia: {v.titulo}
            </h2>
            {v.rolls.map((v, i) => {
              return (
                <div
                  className="grid dark:border-white border-black border-2 rounded-md p-2 gap-2 "
                  key={i}
                >
                  <div className="border-b-2 dark:border-white border-black flex justify-between">
                    <span>Medida:</span>
                    <span>{v.medida}</span>
                  </div>

                  <div className="border-b-2 dark:border-white border-black flex justify-between">
                    <span>Existencia:</span>
                    <span>{v.existencia}</span>
                  </div>

                  <div className="border-b-2 dark:border-white border-black flex justify-between">
                    <span>ID:</span>
                    <span>{v.id}</span>
                  </div>

                  <button
                    className="py-2"
                    onClick={selectARoll}
                    value={v.id}
                    whileHover={{ y: -3 }}
                    whileTap={{ y: 0 }}
                  >
                    select
                  </button>
                </div>
              );
            })}
          </section>
        );
      })}

      <section className="py-4">
        <h2 className={"text-orange-400 font-bold text-2xl"}>
          Control de rollos
        </h2>
        <h3 className="py-4 font-bold text-2xl">
          Selected roll: {selectedRoll}
        </h3>
        {/* 
            I would like to display all the object's information here. 
            Right now it's just a string.
        */}



        {/* 
            This is an extra, but it would be nice to be able to modify the 
            existing quantity of rolls with these buttons. Maybe it is for 
            another question, please let me know.
        */}
        <span>Quantity of rolls used today:</span>
        <div className="flex py-4 gap-4">
          <div className="md:w-1/4 w-full flex justify-between font-bold text-xl">
            <button
              className="border-2 dark:border-white border-black rounded-md px-2"
              onClick={decreaseQuantity}
              whileHover={{ y: -3 }}
              whileTap={{ y: 0 }}
            >
              menos
            </button>
            <span>{quantity}</span>
            <button
              className="border-2 dark:border-white border-black rounded-md px-2"
              onClick={increaseQuantity}
              whileHover={{ y: -3 }}
              whileTap={{ y: 0 }}
            >
              mas
            </button>
          </div>
          <div className="w-1/4  flex content-center justify-center">
            <button
              className="border-2 dark:border-white border-black rounded-md px-2"
              whileHover={{ y: -3 }}
              whileTap={{ y: 0 }}
            >
              confirm
            </button>
          </div>
        </div>
      </section>
    </main>
  );
}

My question is, how can I make selectedRoll the value of the object that was selected? For example, if I press the object button with id MERV820, that the selectedRoll returns all the data of that object?

Please let me know any other thing that you see is wrong or should be better, maybe structure the json different, learn about arrays, I don’t know. Mentoring is appreciated. Thanks.

Here’s the sandbox: https://codesandbox.io/embed/zealous-alex-rqvy2?fontsize=14&hidenavigation=1&theme=dark

Answer

You can use useEffect and the following function called getSelectedRollData to find the object:

import { useState, useEffect } from "react";

useEffect(() => {
    if(selectedRoll){
      getSelectedRollData()
    }
  }, [selectedRoll])


  const getSelectedRollData = () => {
    let parentRollData = null;
    let rollData = null;
    console.log(Rolls)
    for (let i = 0; i < Rolls.length; i += 1) {
      for(let j=0; j<Rolls[i].rolls.length; j+=1){
        if (Rolls[i].rolls[j].id === selectedRoll){
          parentRollData = Rolls[i];
          rollData = Rolls[i].rolls[j]
          break;
        }
      }      
    }

    /// setState, return or console.log()
    console.log(parentRollData);
    console.log(rollData);
  }