pythonista
pythonista

Reputation: 410

Updating array in React JS overwrites old values

I have created a dynamic form in React JS which adds new fields upon clicking the plus button. However when I try to update the form values using the onChange event it overwrite or sometimes deletes the old array. Why is this happening? What is the correct way to dynamically add values to an array?

Below is a screenshot of the error as shown in the console. The array adds the details of the initial person very well but after that when I try to enter "Person 1 details" the old array is somehow cleared. As soon as I enter contact number for Person 1 the array is again cleared.

My code can be found here: https://codesandbox.io/s/awesome-paper-kb7fgf?file=/src/Register.js

enter image description here

Upvotes: 2

Views: 609

Answers (1)

Giorgi Moniava
Giorgi Moniava

Reputation: 28654

This is not the right approach you should not insert JSX elements into state. It is better to insert data in state and then derive UI from it.

The reason that could be causing your problem could be related to stale closures because when you store the JSX in state together with change handlers, the versions of change handlers that get stored belong to that render, hence they capture the formData with values from that render.

Anyway like I said you should discard that approach. I will show you below code how you should approach that problem but you will have to expand this to your use case, this is minimal use case. In this example you can add many persons and each person has input field for name property.

import React from 'react';
import './style.css';
import { v4 as uuidv4 } from 'uuid';

export default function App() {
  let [persons, setPersons] = React.useState({
    [uuidv4()]: {
      name: 'john',
    },
  });
  console.log(persons);
  return (
    <div>
      <button
        onClick={() => {
          setPersons({
            ...persons,
            [uuidv4()]: {
              name: '',
            },
          });
        }}
      >
        Add new person
      </button>
      {Object.entries(persons).map(([k, v]) => {
        return (
          <div key={k}>
            <div>Person </div>
            <input
              value={v.name}
              onChange={(e) => {
                setPersons({
                  ...persons,
                  [k]: {
                    ...persons[k],
                    name: e.target.value,
                  },
                });
              }}
            ></input>
          </div>
        );
      })}
    </div>
  );
}

Upvotes: 4

Related Questions