Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

135
Vistas
Array con entradas en React

Estoy tratando de crear una tabla con una matriz de productos, el problema que tengo es que las entradas toman el valor de cualquier entrada con el mismo "nombre". Además, cuando intento quitar alguno de los productos, siempre quita el último.

https://stackblitz.com/edit/react-gto9bw?file=src/App.js

 const [producto, setProducto] = useState({ codigo: '', nombre: '', descripcion: '', precio: '', cantidad: '', estado: '', }); const [productos, setProductos] = useState([]); const addProducto = () => { setProductos([...productos, producto]); }; const removeProducto = (e, index) => { e.preventDefault(); const list = [...productos]; list.splice(index, 1); setProductos(list); }; const handleInputChangeProducto = (e, index) => { e.preventDefault(); const { name, value } = e.target; const list = [...productos]; list[index][name] = value; setProductos(list); };

La devolución es una tabla que tiene un botón para agregar el producto.

 return ( <div> <table className="table-size" style={{ border: '1px solid black' }}> <thead> <tr> <th scope="col">Nombre</th> <th scope="col">Descripcion</th> </tr> {productos.map((producto, index) => ( <tr key={index}> <td> <input name="nombre" onChange={(e) => handleInputChangeProducto(e, index)} /> </td> <td> <input name="descripcion" onChange={(e) => handleInputChangeProducto(e, index)} /> </td> <td onClick={(e) => removeProducto(e, index)}> <Button>Borrar Producto {index}</Button> </td> </tr> ))} </thead> </table> <br /> <button onClick={addProducto}>Crear Producto</button> </div>

Intenté separar el "tr" en un componente separado, pero tampoco funciona.

about 4 years ago · Santiago Gelvez
3 Respuestas
Responde la pregunta

0

Aunque las otras respuestas no son incorrectas, y todas (implícitamente) solucionaron los problemas a continuación, quería señalar la causa raíz del problema que estaba viendo. No es el uso de índices como claves (aunque tener claves únicas es una buena idea por motivos de rendimiento).

  1. Cuando creó un nuevo producto (al menos en su ejemplo de código original), estaba haciendo esto:

     const addProducto = () => { setProductos([...productos, producto]); };

    Tenga en cuenta que el nuevo producto que se agrega a la matriz es siempre el mismo objeto. Eso significa que su matriz contiene una lista de punteros que apuntan al mismo objeto. Al modificar uno, se modificarán todos. Probablemente eso no es lo que quieres. En su lugar, haz esto:

     const addProducto = () => { setProductos([...productos, {...producto} ]); };

    Eso extiende las propiedades de su objeto de producto en blanco a un nuevo objeto y asegura que cada objeto en la matriz sea realmente una cosa separada.

  2. Los valores del formulario en realidad no estaban controlados por el estado. Partiendo de su ejemplo de código original, realice estos cambios:

     {productos.map((producto, index) => ( <tr key={index}> <td> <input name="nombre" value={producto.nombre} // <-- this was missing. without it there is no relation between what the user is seeing in the input and what value is stored in the productos array. onChange={(e) => handleInputChangeProducto(e, index)} /> </td> <td> <input name="descripcion" value={producto.descripcion} // <-- Same thing here onChange={(e) => handleInputChangeProducto(e, index)} /> </td>
about 4 years ago · Santiago Gelvez Denunciar

0

Este es un problema común cuando se usa un map con index en lugar de una key única.

Así que puedes probar así:

Agregue una key de variable global en su caso.

 let key = 0;

Luego configure esta clave en su producto y auméntela. (En mi código completo, usé codigo como campo key ).

Siempre se debe aumentar.

En la API de back-end, también debe obtener una clave única.

Aquí hay un código completo.

 import React, { useState } from 'react'; import { Button } from 'react-bootstrap'; import './style.css'; let key = 0; export default function App() { const [producto, setProducto] = useState({ codigo: '', nombre: '', descripcion: '', precio: '', cantidad: '', estado: '', }); const [productos, setProductos] = useState([]); const addProducto = () => { setProductos([...productos, { ...producto, codigo: ++key }]); }; const removeProducto = (e, index) => { e.preventDefault(); const list = [...productos]; list.splice(index, 1); setProductos(list); }; const handleInputChangeProducto = (e, index) => { e.preventDefault(); const { name, value } = e.target; const list = [...productos]; list[index][name] = value; setProductos(list); }; console.log({ productos }); return ( <div> <table className="table-size" style={{ border: '1px solid black' }}> <thead> <tr> <th scope="col">Nombre</th> <th scope="col">Descripcion</th> </tr> {productos.map((producto, index) => ( <tr key={producto.codigo}> <td> <input name="nombre" onChange={(e) => handleInputChangeProducto(e, index)} /> </td> <td> <input name="descripcion" onChange={(e) => handleInputChangeProducto(e, index)} /> </td> <td onClick={(e) => removeProducto(e, index)}> <Button>Borrar Producto {index}</Button> </td> </tr> ))} </thead> </table> <br /> <button onClick={addProducto}>Crear Producto</button> </div> ); }
about 4 years ago · Santiago Gelvez Denunciar

0

Necesita una clave única. Intente generar esta clave única en su addProducto :

 const addProducto = () => { setProductos([...productos, { ...producto, id: Date.now() }]); };

Y luego en su productos.map pase esta identificación generada en su <tr key={producto.id}> .

Se recomienda que tenga índices "estáticos" como clave, React entenderá mejor cómo manipular su lista y si ocurre alguna modificación en esta lista, no recalculará todo.

Otro punto, si necesita manipular algo que depende de su estado anterior, como estas operaciones de agregar o quitar, intente usar funciones para actualizaciones, como:

 const addProducto = () => { setProductos(prevProductos => [...prevProductos, { ...producto, id: Date.now() }]); }; const removeProducto = (e, index) => { e.preventDefault(); setProductos(prevProductos => [...prevProductos.slice(0, index), ...prevProductos.slice(index + 1)]); };
about 4 years ago · Santiago Gelvez Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda