how to handle multiple values through 'useState' hook in React?

Viewed 25

Here I've used useState hook in React to handle change in input field of form, but I've repeated same code multiple times and I want to shorten it. Is there any possible way to handle multiple changes through single state and give output in object?

import React, { useState } from "react";
    
    const [enteredTitle, setEnteredTitle] = useState("");
    const [enteredPrice, setEnteredPrice] = useState("");
    const [enteredDate, setEnteredDate] = useState("");
    
    const titleChangeHandler = (e) => {
      setEnteredTitle(e.target.value);
    };
    const priceChangeHandler = (e) => {
      setEnteredPrice(e.target.value);enter code here
    };
    const DateChangeHandler = (e) => {
      setEnteredDate(e.target.value);
    };
    const handleSubmit = (e) => {
      e.preventDefault();
    
      const expenseData = {
        title: enteredTitle,
        price: enteredPrice,
        date: new Date(enteredDate),
      };
      props.newExpense(expenseData);
    
      setEnteredTitle("");
      setEnteredPrice("");
      setEnteredDate("");
    };
    
    return (
      <form onSubmit={handleSubmit}>
        <div className="new-expense__controls">
          <div className="new-expense__control">
            <label htmlFor="">Title</label>
            <input
              onChange={titleChangeHandler}
              type="text"
              name="title"
              value={enteredTitle}
            />
          </div>
          <div className="new-expense__control">
            <label htmlFor="">Amount</label>
            <input
              onChange={priceChangeHandler}
              type="number"
              name="price"
              value={enteredPrice}
              min="0.01"
              step="0.01"
            />
          </div>
          <div className="new-expense__control">
            <label htmlFor="">Date</label>
            <input
              onChange={DateChangeHandler}
              type="date"
              name="date"
              value={enteredDate}
            />
          </div>
        </div>
        <div className="new-expense__actions">
          <button type="submit">Submit</button>
        </div>
      </form>
    );
    };
    export default ExpenseForm;
1 Answers

Each individual state value doesn't have to be a single value, it can be an object:

const [enteredData, setEnteredData] = useState({
  title: '',
  price: '',
  date: ''
});

And you can use a single change handler as long as your <input> elements have correct name attributes, since the e.target object also has that name. For example:

const changeHandler = (e) => {
  setEnteredData({
    ...enteredData,
    [e.target.name]: e.target.value
  });
};

This would update the state object to include all the properties of the current state object, but specify one property (from the given name) to have the new given value.

Then your <input> elements can just use that object and handler function:

<input
  onChange={changeHandler}
  type="text"
  name="title"
  value={enteredData.title}
/>
Related