React - Dynamic table - Adding and removing rows from the table

Asked

Viewed 406 times

-1

I wrote the following code below, it is 100% functional with one exception.

By clicking "remove" on the desired line, it removes the last line, not the correct one (that is, add 5 lines, ask q to remove the second, and actually remove the last).

Curious that in the array it removes correctly, the problem is only in the view.

The code is very simple and functional, copying and compiling anywhere should work well.

Can you help me with this last missing item (referring to removing the correct line - preferably using typescript)? Thank you.

import React, { useState } from 'react';

export default function Test() {  
    const [infos, setInfos] = useState([
        { 'info1': '', 'info2': '', 'info3': '' }
    ]);
    
    function addNewInfoItem() {
        setInfos([
            ...infos,
            { 'info1': '', 'info2': '', 'info3': '' }
        ]);
    };

    function removeInfoItem(index: any) {
        const itensCopy = Array.from(infos);
        itensCopy.splice(index, 1);
        setInfos(itensCopy);
    };

    function updateInfosItem(position:number, field:string, item:string) {
    const updatedInfoItems = infos.map((standardItem, index) => {
        if (index === position) {
            return { ...standardItem, [field]: item }
        }
        return standardItem
    })
    setInfos(updatedInfoItems)
  }

  return (
    <div>
        {infos.map((item, index) => {
            return (
                <div key={index}>
                    <button onClick={e => removeInfoItem(index)}> Remover </button>
                    <input
                        required
                        type="text"
                        onChange={e => updateInfosItem(index, 'info1', e.target.value)}
                    />
                    <input
                        required
                        type="text"
                        onChange={e => updateInfosItem(index, 'info2', e.target.value)}
                    />
                    <input
                        required
                        type="text"
                        onChange={e => updateInfosItem(index, 'info3', e.target.value)}
                    />
                </div>
            );
        })}
        <pre> {JSON.stringify(infos, null, 4)} </pre>
        <button onClick={addNewInfoItem}> Adicionar </button> 
    </div>
  );
}

1 answer

1


Basically, what happened to your code is exhibiting strange behavior, is the fact that you haven’t set a default value for these inputs. Also because, as you said, it is removed correctly from the array of state, then the problem is not the logic itself, but the time to display the data.

To solve this, just add one value={infos[index].info<equi>} equivalent in each of the inputs, i.e.:

  • value={infos[index].info1} in the first input;
  • value={infos[index].info2} in the second input;

and so on...

Would look like this:

function App() {
  const [infos, setInfos] = React.useState([{ info1: '', info2: '', info3: '' }]);
  
  
  function addNewInfoItem() {
    setInfos([...infos, { info1: '', info2: '', info3: '' }]);
  }

  function removeInfoItem(index: any) {
    const itensCopy = Array.from(infos);

    itensCopy.splice(index, 1);

    setInfos(itensCopy);
  }

  function updateInfosItem(position: number, field: string, item: string) {
    const updatedInfoItems = infos.map((standardItem, index) => {
      if (index === position) {
        return { ...standardItem, [field]: item };
      }

      return standardItem;
    });

    setInfos(updatedInfoItems);
  }

  return (
    <div>
      {infos.map((item, index) => {
        return (
          <div key={index}>
            <button onClick={(e) => removeInfoItem(index)}> Remover </button>
            <input
              required
              type="text"
              onChange={(e) => updateInfosItem(index, 'info1', e.target.value)}
              value={infos[index].info1}
            />
            <input
              required
              type="text"
              onChange={(e) => updateInfosItem(index, 'info2', e.target.value)}
              value={infos[index].info2}
            />
            <input
              required
              type="text"
              onChange={(e) => updateInfosItem(index, 'info3', e.target.value)}
              value={infos[index].info3}
            />
          </div>
        );
      })}
      <pre> {JSON.stringify(infos, null, 4)} </pre>
      <button onClick={addNewInfoItem}> Adicionar </button>
    </div>
  );
}

ReactDOM.render( < App / > , document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.1/umd/react-dom.production.min.js"></script>
<div id="root"></div>

Run the tests and see if you’ve solved your problem.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.