Home > Software design >  Need to find object from an array with two objects
Need to find object from an array with two objects

Time:01-17

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

CodePudding user response:

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

CodePudding user response:

I assumed you want to pass in the whole object when you click on Select

I changed where you call the selectARoll function and passed the whole object

onClick={()=>selectARoll(v)}

Then I changed the selectARoll function to take in the object

  const selectARoll = (v:any) => {
    setSelectedRoll(v);
  };

Now your state has the whole object and can be accessed like selectedRoll.id etc.

Maybe change your initial state to something like

const [selectedRoll, setSelectedRoll] = useState({id:"none"});

PS unrelated. I haven't used typescript and cannot say much but if you using typescript avoid using any as it looses the purpose of using typescript

  •  Tags:  
  • Related