3

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 Lists and Keys.

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.

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
ReactPotato
  • 1,262
  • 3
  • 26
  • 46
  • I'm not sure about your question but you can use some tricks to generate ID in-place. Using `nanoId` node package or `Date Object` in `JS` -> *`new Date().getTime().toString()`* – Erfan Motallebi Sep 19 '21 at 15:58
  • Correct me if I'm understanding, but you want the rows to go 1, 2, 3, 4.... – Andrew Sep 19 '21 at 15:58
  • @Andrew I want all of them to be 1, cantidad/amount is the amount of books you would like, so it will start with 1 if you wanna add more books of the same then it goes to -> mas/plus and menos/minus which are the 2 buttons. – ReactPotato Sep 19 '21 at 16:04
  • @ErfanMotallebi I'll look into it. – ReactPotato Sep 19 '21 at 16:04

1 Answers1

1

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>
)}
Sangam Rajpara
  • 652
  • 3
  • 12
  • 1
    This could work, but why do we need to create a new array every time a new book is added or changed? I think this is bad for performance and doesn't seem intuitive / good practice. – Andrew Sep 19 '21 at 16:07
  • This worked, but w/e I try to use the functions ```mas``` or ```menos``` it goes back to blank idk what I'm doing wrong there. – ReactPotato Sep 19 '21 at 16:09
  • Instead of setting value 1s when new `libros` is added you need to just add 1 at end of the array. So inside use effect check that both arrays have different lengths add 1s at the end or remove the propert value. – Sangam Rajpara Sep 19 '21 at 16:17
  • Question @SangamRajpara why does the functions are not working, did I set them up wrong ? – ReactPotato Sep 19 '21 at 16:37