Save latest string values in react state array

Viewed 548

I have a form in react containing multiple text boxes. I am trying to fetch the values of all text boxes on click of a button. For that I am using an array of states. Here´s my state which is an array of objects:

const [myState, setMyState] = useState([{
   stringValue: {
      name: "",
      value: ""
   },
       
}])

And here´s my text field:

<TextField 
  onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
      setMyState([...myState, {
        stringValue: {
          name: displayName,
          value: e.target.Value
        }
      },])}
/>

On button click I want to get the values of all textboxes but since I am using a state array, my myState array looks something like this :

h
he
hel
hell
hello

If I don´t use state array, I end up overwriting the state. How can I get I save the full string "hello" to myState instead of all the individual characters?

2 Answers

You don't need an array to save and retrieve the values of all the input fields in the form.

Instead of using an array, use a object literal that will hold the values of all the input fields in the form. Your state could have the following structure

const [data, setData] = useState({
   input1: '',
   input2: '',
   input3: ''
});

And make each input field a controlled component, meaning its value will be driven by the state of the component.

This way you can access the values of all the fields and update the value of the input fields using only a single onChange event handler.

const handleChange = (event) => {
   const { name, value } = event.target;
   setData({ ...data, [name]: value });
};

Following code snippet shows an example:

function App() {
  const [data, setData] = React.useState({
    input1: "",
    input2: "",
    input3: ""
  });

  const handleChange = (event) => {
    const { name, value } = event.target;
    setData({ ...data, [name]: value });
  };

  return (
    <div>
      <input
        type="text"
        name="input1"
        value={data.input1}
        onChange={handleChange}
      />
      <input
        type="text"
        name="input2"
        value={data.input2}
        onChange={handleChange}
      />
      <input
        type="text"
        name="input3"
        value={data.input3}
        onChange={handleChange}
      />
      <br />
      {JSON.stringify(data)}
    </div>
  );
}

ReactDOM.render(<App/>, document.getElementById('root'));
input { display: block; }
<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>

Edit:

If you want to create input fields dynamically, then you can create the input fields dynamically using the the array or an object that represents the different input fields in the form.

Following code snippet shows an example:

function App() {
  const [data, setData] = React.useState({
    input1: { type: "text", value: "", name: "input1" },
    input2: { type: "text", value: "", name: "input2" },
    input3: { type: "text", value: "", name: "input3" }
  });

  const handleChange = (event) => {
    const { name, value } = event.target;
    setData({ ...data, [name]: { ...data[name], value } });
  };

  return (
    <div>
      {Object.keys(data).map((k) => {
        const { type, value, name } = data[k];
        return (
          <input
            key={k}
            type={type}
            value={value}
            name={name}
            onChange={handleChange}
          />
        );
      })}
      <br />
      {/* just for demo */}
      {Object.keys(data).map((k) =>
        JSON.stringify({ name: data[k].name, value: data[k].value })
      )}
    </div>
  );
}

ReactDOM.render(<App/>, document.getElementById('root'));
input { display: block; margin: 8px 0; }
<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>

add value in TextField

<TextField
value={state.value}
Related