Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Array with inputs in React

Im trying to create a table with an array of products, the problem I have is that the inputs take the value of any input with the same "name". Also, when I try to remove any of the products, it always removes the last one.

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);
  };

The return its a table that has a button to add the product

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

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>

I’ve tried separating the "tr" into a separate component but that doesn’t work either.

>Solution :

This is a common issue when using map with index instead of unique key.

So you can try like this:

Please add a global variable key in your case.

let key = 0;

Then set this key in your producto and increase it.
(In my full code, I used codigo as a key field.)

It should always be increased.

On backend API, you should get unique key as well.

Here is a full code.

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>
  );
}

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading