How to store and update objects in React useState hook
Published: 2022-08-12 13:13:47

In my previous article, I have explained [how to store and update arrays in useState hook](https://www.codingdeft.com/posts/react-usestate-array/). 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:

```bash
npx create-react-app react-usestate-object
```

## Updating the state object

Let's create 2 fields with `firstName` and `lastName`:

```jsx
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:

```jsx
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](https://www.codingdeft.com/posts/react-three-dots-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:

```jsx
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](https://www.codingdeft.com/posts/react-form-validation/),
which helps for form validation as well.