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.
Top comments (0)