Home > Enterprise >  REACT JS: How to add a Key to an array that hasn't been initiated, inside a map?
REACT JS: How to add a Key to an array that hasn't been initiated, inside a map?

Time:09-21

I been trying for a few days to solve this piece of code and have successfully slowly progress through it but I'm still stuck sadly here's the issue:

First of all what I want to achieve is to display an Array of X with all the values starting on 1 someone gave me a hint and I try it but it doesn't seem to be working and is Probably because I'm not assigning a "key" to it

const [cantidad, setCantidad] = useState( new Array(libros.length).fill(1) );

This is supposedly will create an array with all values starting on 1 if I'm not wrong.

but this is what is printing:

enter image description here

when I manually assigned 1 as a value at least to the first one it looks like this:

enter image description here

But since I'm manually just setting up const [cantidad, setCantidad] = useState([1]); it clearly won't work because is just the first value, which is why I try the previous code const [cantidad, setCantidad] = useState( new Array(libros.length).fill(1) ); but that didn't work sadly (or maybe I'm just missing the key component), because that's the error it gives me (I'm not even using li/list though) here's where it sends me is basically a list/key information but it seems that key is the equivalent of my "index" value I gave in the start enter image description here

Anyways moving on, The idea is to increases the amount/cantidad of the number with 2 functions called mas and menos, is quite simple if you click the button on the left it adds 1 and if is the one on the right it does -1 that I think is covered correctly:

const mas = (index) => {
        setCantidad(cantidad[index]   1);
      };

      const menos = (index) => {
        if (cantidad[index] > 0){
            setCantidad(cantidad[index] - 1);
        }
        else {
            window.alert("Sorry, Zero limit reached");
            setCantidad(0);
        }
      };

Finally this is how I'm printing the table

<tbody>
                {libros.map((libros, index) => (
                        <tr >
                        <td>
                            <button onClick = {() => mas(index)}/>
                            {cantidad[index]}
                            {console.log(cantidad)}
                            {console.log([index])}
                            <button onClick = {() => menos(index)}/>
                        </td>
                        <td>{libros.grado}</td>

                        <td >
                        <input onChange = {(event) => {
                            let checked = event.target.checked;
                        }} 
                        
                        type="checkbox" checked = "">
                        </input>
                        {libros.descripcion}
                        </td>

                        <td >{libros.editorial}</td>
                        <td >${parseFloat(libros.precio).toFixed(2) * cantidad[index]}</td>
                        </tr>

                     ))}
                </tbody>

This is what the console log is showing: enter image description here

I have read array and map and I understand the basics on a regular situation didn't saw a similar example of my current situation any help/tips is appreciate it, here's my actual code (whole code):

import React, { useState, useEffect } from 'react'
import { auth, db } from './firebase';
import { useHistory } from 'react-router-dom';
import { Checkbox } from '@material-ui/core';

function CrearPedidos({user}) {
    const [libros, setLibros] = useState([]);
    const [cantidad, setCantidad] = useState( new Array(libros.length).fill(1));

    const history = useHistory("");
    const [totalPrice, setTotalPrice] = useState();

    const librosRef = db.collection('libros');
    const queryRef = librosRef.where('grado', '==', '4° Grado');

   console.log(cantidad)

    useEffect(() => {
        queryRef.orderBy("precio")
        .get()
        .then((snapshot) => {
              const tempData = [];
            snapshot.forEach((doc) => {

              const data = doc.data();
              tempData.push(data);
            });
            setLibros(tempData);
          });
      }, []);

      const mas = (index) => {
        setCantidad(cantidad[index]   1);
      };

      const menos = (index) => {
        if (cantidad[index] > 0){
            setCantidad(cantidad[index] - 1);
        }
        else {
            window.alert("Sorry, Zero limit reached");
            setCantidad(0);
        }
      };

    return (
        <div className="listado_Pedidos"> 
        <div className="estudiantes_container">
            <h1 className = "estudiantes_container_h1">Estudiante: {user.displayName}</h1>
            <h1 className = "estudiantes_container_h1">Libros Nuevos</h1>
            <div className ="tableContainer">
            <table>
                <thead>
                    <tr className="Lista">
                        <th>Cantidad</th>
                        <th>Grado</th>
                        <th>Descripcion</th>
                        <th>Editorial</th>
                        <th>Precio</th>
                    </tr>
                </thead>
                <tbody>
                {libros.map((libros, index) => (
                        <tr >
                        <td>
                            <button onClick = {() => mas(index)}/>
                            {cantidad[index]}
                            {console.log(cantidad)}
                            {console.log([index])}
                            <button onClick = {() => menos(index)}/>
                        </td>
                        <td>{libros.grado}</td>

                        <td >
                        <input onChange = {(event) => {
                            let checked = event.target.checked;
                        }} 
                        
                        type="checkbox" checked = "">
                        </input>
                        {libros.descripcion}
                        </td>

                        <td >{libros.editorial}</td>
                        <td >${parseFloat(libros.precio).toFixed(2) * cantidad[index]}</td>
                        </tr>

                     ))}
                </tbody>
            </table>
            </div>

            <div className="space" />
            <button onClick="{realizarPedidos}" className = "crear_estudiante_boton">Realizar Pedidos</button>
            <div className="space" />
      </div>

      </div>
    )
}

export default CrearPedidos

I know I been doing lots of questions lately buuuut I wanna learn and practice all I can, oh also I'm using Firebase for my database the only value that is not from the database is cantidad/amount all the others grado/course descripcion/description, etc are from the database which is why I haven't had issues with those.

CodePudding user response:

Your question is a bit unclear but I have found the below problem in your code.

You are setting the default value to the cantidad state using another state libros but it'll be set only once when your component renders for the first time. So you should use useEffect hook here to update the cantidad whenever libros change.

useEffect(()=>{
  setCantidad(new Array(libros.length).fill(1))
}, [libros])

Always use keys when looping over some array and rending list of component.

{libros.map((libros, index) => (
    <tr key={libros.id || index}>
      ...
    </tr>
)}
  • Related