#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. нет, к сожалению, похоже, это не работает, извините, я отредактирую свой вопрос, чтобы показать вам, что печатается.