In this article, Let's learn about Making React State Flexible: A Closer Look at Object State with useState

This article delves into the nuances of React state management, specifically focusing on using objects with the useState hook to achieve a new level of flexibility and control in your applications

Table of Contents

Create a Functional Component

I'm going to create a new file called HookCounterThree.js, within the file I'm going to u create a functional component.

import React, { useState } from 'react'

function HookCounterThree() {
return (
<div>
HookCounterThree
</div>
)
}

export default HookCounterThree

for the next step,  I'm going to import useState from react and create state variable, the default value with be an object, the object will contain firstName and lastName initialised to an empty string.

Initialise Object using useState

import React, { useState } from 'react'

function HookCounterThree() {
const [name, setName] = useState({ firstName: '', lastName: '' })
return (
<div>
HookCounterThree
</div>
)
}

export default HookCounterThree


Note -  an important point to keep in mind a state variable can be a string, a number, boolean, an object or even an array.  You can use any of those types based on your requirement.


Alright so we now have a state variable called mean which is an object and a setter function setName to update the corresponding state variable.


Add two input fields in render function

let's define the render function, you basically want to have two input fields one for first-name and one for last name.

So let's add a form tag an input element type is equal to text this is for the first name and a second one for the last name below the input fields we simply display the first name and the last name you can add an h2 tag your first name is name dot first name and similarly your last name is name dot last name.


Next, let's handle the value attribute and the onChange event on the two input fields for first name value is going to be equal to name dot first name and onChange that is whenever the user starts typing in something we want to set the first name property.

import React, { useState } from 'react'

function HookCounterThree() {
const [name, setName] = useState({ firstName: '', lastName: '' })
return (
<form>
<input
type="text"
value={name.firstName}
onChange={e => setName({ firstName: e.target.value })}
/>
<input
type="text"
value={name.lastName}
onChange={e => setName({ lastName: e.target.value })}
/>
<h2>Your first name is - {name.firstName}</h2>
<h2>Your last name is - {name.lastName}</h2>
     <h2>{JSON.stringify(name)}</h2>
</form>
)
}

export default HookCounterThree

setName - is our function call which will set the name of state variable and what do we want to set we want to set first name equal to event dot target dot value and let's do the same for last name. I'm going to copy this input tag and replace the second one. I'm going to change value to name dot last name and in the setName function last name is going to be equal to e dot target dot value.

So basically whenever the first input field value changes we update the first name property and when the second input field value changes we update the last name property.

Set the state variable on change event

onChange={e => setName({ firstName: e.target.value })}
onChange={e => setName({ lastName: e.target.value })}

let's test this out meant to include hook counter three in App.js, save the files and head to the browser and type in the first input field  and you can see that the first name is now displayed. And then  start typing in the second input field and you can see that we have a problem the last name is displayed fine but then the first name is now empty. If I start typing in the first input field we have the first name but the last name is now empty.

So there is something happening with the state variable to visualise that I'm going to go back to VS code and add another line in the JSX I'm going to display the name state variable.

<h2>{JSON.stringify(name)}</h2>

If you now go back to the browser you can see that by default we have both first-name and lastname set to empty strings.

Now when I start typing in the first name the last name property is removed from the state variable. If I start typing in the last name the first name property disappears from the state variable.

The reason this happens is because  useState does not automatically merge and update the object, this is a key difference to setState which you come across in class components. setState will merge the state whereas the useState hook set of function will not merge the state.

You have to do it manually it's not difficult though because we can use the spread operator to handle the manual merge so back in vs code on change and the arrow function we first spread name and then set the appropriate property spread the name and then overwrite last name how do you read this is hey copy every property in the name object and then just overwrite the first name field with a different value similarly for last name just make a replica of the name object and then only up the last name property to the new value.

Complete example code

import React, { useState } from 'react'

function HookCounterThree() {
const [name, setName] = useState({ firstName: '', lastName: '' })
return (
<form>
<input
type="text"
value={name.firstName}
onChange={e => setName({ ...name, firstName: e.target.value })}
/>
<input
type="text"
value={name.lastName}
onChange={e => setName({ ...name, lastName: e.target.value })}
/>
<h2>Your first name is - {name.firstName}</h2>
<h2>Your last name is - {name.lastName}</h2>
<h2>{JSON.stringify(name)}</h2>
</form>
)
}

export default HookCounterThree

The spread operator which is a feature of es6 is a very common operator in use now. If you are new to this,  do spend a few minutes to understand the spread operator and then resume the article, so if you now save the file and go back to the browser type in the first name the first name is updated but you can see that the last name property is preserved type in the last name the first name is as it is and the last name is updated with the new value.

So this is the third example, I wanted to discuss to highlight one key point the setter function provided by the useState hook does not automatically merge and update objects, you have to manually merge it yourself and then pass the value to the setter function.

Now we have a similar scenario when updating arrays so let's quickly take a look at that example in the next article. 


Conclusion

In the world of React development, state management is a critical skill. This article has taken a closer look at object state variables with the useState hook, shedding light on the power and flexibility they bring to your applications. By following the best practices and optimization strategies outlined here, you'll be better equipped to tackle the challenges of state management in your React projects.

To learn more about UseState hook, please go through below links

React hooks introduction

React useState hook

How to set state based on the previous state value?

How to use the state hook when the state variable is an array?