Skip to main content

Command Palette

Search for a command to run...

How to store and update objects in React useState hook

Published
2 min readView as Markdown
How to store and update objects in React useState hook
A

Blogger at codingdeft.com

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

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

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

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

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.

More from this blog

CodingDeft

32 posts