Как заполнить массив одинаковыми значениями X раз и как правильно отправить данные в функцию?

#arrays #reactjs #array-map

Вопрос:

Я задал аналогичный вопрос, связанный с массивами и картами, но получил ответ только на половину, поэтому я выделяю этот вопрос отдельно.

У меня есть этот код (только соответствующая информация):

 const [libros, setLibros] = useState([]);
const [cantidad, setCantidad] = useState([1]);

//This is not finished because I'm still stuck
const mas = (index, value) => {
        setCantidad(cantidad[index]   1);
      };

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


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

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

//I know this check is not working properly I'm strill trying to figure out this one 

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

   ))}
</tbody>

 

Я знаю, что в javascript вы можете сделать следующее:

 Array(5).fill(2)
//=> [2, 2, 2, 2, 2]
 

Есть ли способ сделать что-то подобное в React? потому что я хочу добиться следующего:
«cantidad» всегда будет начинаться с 1, а затем предоставит пользователю возможность изменить эту сумму 1 или -1 в зависимости от того, сколько элементов он/она хочет, но я не знаю, как установить все значения на 1, при этом, как говорится, кто-то уже направил меня, прежде чем сказать мне, что, добавив значение индекса на карте, я могу управлять ими индивидуально, я не понимаю, как применить это в своем коде, потому что я хотел бы отправить текущий индекс и текущее значение этого индекса в

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

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

функции, которые я создал, вот как печатается банкомат, я вроде как понимаю, как это сделать, если вы уже настроили X количество значений в массиве, но не тогда, когда количество значений зависит от количества повторений карты, я пытаюсь использовать map.length, но не сработало, любые советы/советы приветствуются

введите описание изображения здесь

Это весь код

 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(queryRef)

    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((l, index) => (
                        
                        <tr >
                        
                        <td>
                            <button onClick = {() => mas(index)}/>
                            {cantidad[index]}
                            <button onClick = {() => menos(index)}/>
                        </td>
                        <td>{l.grado}</td>

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

                        <td >{l.editorial}</td>
                        <td >${parseFloat(l.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
 

Вот как это выглядит и что показывает cantidad в журналах

введите описание изображения здесь

Комментарии:

1. Первое, что я заметил, было const [cantidad, setCantidad] = useState([1]) тогда чуть ниже: setCantidad(cantidad[index] 1); . Это намеренно? Вы инициализируете его как массив ( [] ) с номером 1 , но затем меняете тип на число, а не на массив.

2. эх, на самом деле мои навыки кодирования в React не очень грубые/плохие, поэтому я просто пробовал разные вещи.

Ответ №1:

setCantidad При использовании вашего метода необходимо установить новый массив, содержащий увеличенное значение, а не увеличенное значение одного из его элементов.

Вы инициализируете useState массив, но позже меняете его с массива только на значение одного из этих элементов в массиве.

Если быть точным, вы инициализируете cantidad , чтобы быть [1] , что то же самое, что new Array(1).fill(1) . Однако позже вы установите cantidad значение «быть cantidad[index] 1 «, которое (при index условии, что оно есть 0 ) будет означать, что вы меняетесь cantidad с [1] «на 2 «. Он перешел от массива с номером к просто номеру.

Чтобы сохранить cantidad его в виде массива, вы должны установить его с новым массивом, когда он изменится. setCantidad он просто существует для обновления вашего состояния новым значением; он не знает и не заботится о том, с чем он был инициализирован или ранее установлен как.

Таким образом, вы можете обновить его многими способами. Вот одно предложение:

 const mas = (index) => {
  cantidad[index] = cantidad[index]  
  // Note how we're setting it with a new array, not the original. 
  // It is important to know how JS references objects (such as arrays) vs other types 
  // by using its pointer as the source of truth vs its pure bytes, respectively
  setCantidad([...cantidad]);
};

const menos = (index, value) => {
  if (cantidad[index] > 0){
    cantidad[index] = cantidad[index]--
    setCantidad([...cantidad]);
  } else {
    window.alert("Sorry, Zero limit reached");
    // no need to do any setting here as the indexed value should already be zero based on the condition above
  }
};
 

Комментарии:

1. Ооо, это было то, что некоторые люди пытались объяснить, но я не понял, что они имели в виду, вернув значение 1 вместо массива, теперь это имеет такой смысл. У меня просто вопрос, что это setCantidad([...cantidad]) значит ? как ...cantidad будто я новичок, чтобы так реагировать… Я не понимаю некоторых основных вещей, подобных этому. Любая ссылка на документацию будет признательна. Я буквально собирался задать вопрос по этому поводу, кстати, спасибо за это!

2. Это называется «назначение деструкции», и вы можете подробно прочитать, как это работает на developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…

Ответ №2:

Вы можете инициализировать cantidad массив в зависимости от libros.length

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

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

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

Комментарии:

1. По какой-то причине я не могу использовать Array , это потому, что я не расширяюсь, React.Component если это так, есть ли другие обходные пути ?

2. в nvm была опечатка, я попытался сделать то, что вы написали, и это все равно не сработало :c

3. попробуйте сделать это new перед Array (отредактированным ответом, чтобы помочь)

4. нет, к сожалению, похоже, это не работает, извините, я отредактирую свой вопрос, чтобы показать вам, что печатается.