DEV Community

Cover image for How to store and update objects in React useState hook
collegewap
collegewap

Posted on • Originally published at codingdeft.com

How to store and update objects in React useState hook

In my previous article, I have explained how to store and update arrays in useState hook. In this article, we will see how to modify the objects stored using the useState hook.

Project Setup

Create a react project using the following command:

npx create-react-app react-usestate-object
Enter fullscreen mode Exit fullscreen mode

Updating the state object

Let's create 2 fields with firstName and lastName:

import { useState } from "react"

function App() {
  const [name, setName] = useState({ firstName: "", lastName: "" })

  return (
    <div className="App">
      <div>
        <label htmlFor="firstName">First Name: </label>
        <input
          type="text"
          name="firstName"
          id="firstName"
          value={name.firstName}
        />
      </div>
      <div>
        <label htmlFor="lastName">Last Name: </label>
        <input
          type="text"
          name="lastName"
          id="lastName"
          value={name.lastName}
        />
      </div>
      <div>
        Name is: {name.firstName} {name.lastName}
      </div>
    </div>
  )
}

export default App
Enter fullscreen mode Exit fullscreen mode

Here we have the name object as the local state to store the firstName and lastName. Currently, these fields are read-only.

Let's go ahead and add onChange functions to these fields and update the state object when the users type in the input field:

import { useState } from "react"

function App() {
  const [name, setName] = useState({ firstName: "", lastName: "" })

  const setFirstName = e => {
    setName(existingValues => ({
      // Retain the existing values
      ...existingValues,
      // update the firstName
      firstName: e.target.value,
    }))
  }

  const setLastName = e => {
    setName(existingValues => ({
      // Retain the existing values
      ...existingValues,
      // update the lastName
      lastName: e.target.value,
    }))
  }

  return (
    <div className="App">
      <div>
        <label htmlFor="firstName">First Name: </label>
        <input
          type="text"
          name="firstName"
          id="firstName"
          value={name.firstName}
          onChange={setFirstName}
        />
      </div>
      <div>
        <label htmlFor="lastName">Last Name: </label>
        <input
          type="text"
          name="lastName"
          id="lastName"
          value={name.lastName}
          onChange={setLastName}
        />
      </div>
      <div>
        Name is: {name.firstName} {name.lastName}
      </div>
    </div>
  )
}

export default App
Enter fullscreen mode Exit fullscreen mode

Here, we make use of the spread operator to retain the existing values and update only the required values.

Combining the update to a single function

Since the functionality in updating both the fields are same, we can write a common update function as shown below:

import { useState } from "react"

function App() {
  const [name, setName] = useState({ firstName: "", lastName: "" })

  const updateName = e => {
    const fieldName = e.target.name
    setName(existingValues => ({
      // Retain the existing values
      ...existingValues,
      // update the current field
      [fieldName]: e.target.value,
    }))
  }

  return (
    <div className="App">
      <div>
        <label htmlFor="firstName">First Name: </label>
        <input
          type="text"
          name="firstName"
          id="firstName"
          value={name.firstName}
          onChange={updateName}
        />
      </div>
      <div>
        <label htmlFor="lastName">Last Name: </label>
        <input
          type="text"
          name="lastName"
          id="lastName"
          value={name.lastName}
          onChange={updateName}
        />
      </div>
      <div>
        Name is: {name.firstName} {name.lastName}
      </div>
    </div>
  )
}

export default App
Enter fullscreen mode Exit fullscreen mode

Here we have used [variableContainingPropertyName] notation to set the appropriate object value.

If there are many fields, you can make use of the useReducer hook,
which helps for form validation as well.

Top comments (0)