A ReactJS Hook : useState()
Jeet Bhalani
Posted on May 19, 2022
useState is a Hook that enables state variables to be used in functional components. This function takes the initial state and returns a variable with the current state value and another function to update it.
In React, there are two type of components class based and functional based. Functional components are simple functions that accept parameters as component properties and return valid JSX:
function React(props) {
return <div>{props.useState}</div>
}
// Or as an arrow function
const React = (props) => <div>{props.useState}</div>
There are no state or lifecycle methods, as you can see.
React Hooks are the functions that add state variables to functional components. They usually begin with the keyword use.
How to use useState
Hook in ReactJS? What does it do?
useState allows you to add state to function components, as previously indicated. When you use useState inside a function component, it creates a single piece of state for that component.
Whereas in a class, the state is always an object, Hooks' state can be any type. Each state item contains a single value, which can be an object, an array, a boolean, or any other kind you can think of.
So, when is it appropriate to utilize the useState Hook? It's particularly effective for the local component state, but larger projects may require the usage of additional state management methods.
Declaring{ useState }
in your React App.
To use the UseState hook in your App simply type the following code:
import React, { useState } from 'react';
The useState
Hook allows you to declare only one state variable (of any type) at a time, like this:
import React, { useState } from 'react';
const React= () => {
const message = useState( '' );
const listOfMessage = useState( [] );
}
useState
takes the initial value of the state variable as an argument.
You can pass it directly, as shown in the previous example, or use a function to initialize the variable.
const Message= () => {
const message = useState( () => helloWorld() );
}
The initial value will only be assigned on the first render and if it's a function, it will only be called on the first render.
The initial parameter of the useState Hook will be ignored in subsequent renders (due to a change of state in the component or a parent component) and the current value will be obtained.
Because its argument is only used for the first time — not every time the property changes — using useState alone won't work.
However, unlike the previous examples, useState does not just return a variable.
It returns an array with the state variable as the first element and a function to update the variable's value as the second element.
Array destructuring
is commonly used to simplify the code.
const React= () => {
const [message, setMessage]= useState( '' );
}
Updating the useState
in React Hooks
The second element returned by useState
is a function that updates the state variable with a new value.
Here's an example of how to update the state variable.
const React = () => {
const [message, setMessage] = useState( '' );
return (
<div>
<input
type="text"
value={message}
placeholder="Enter a text"
onChange={e => setMessage(e.target.value)}
/
</div>
);
};
This update function, on the other hand, does not immediately update the value.
The useState
parameter will be ignored after re-rendering the component, and this function will return the most recent value or the new state values.
Using state varibales as an object: In useState()
Hooks
If we add another property to the message object (id) like in the previous example:
const React = () => {
const [messageObj, setMessage] = useState({ message: '', id: 1 });
return (
<div>
<input
type="text"
value={messageObj.message}
placeholder="Enter a message"
onChange={e => {
const newMessageObj = { message: e.target.value };
setMessage(newMessageObj);
}}
/>
<p>
<strong>{messageObj.id} : {messageObj.message}</strong>
</p>
</div>
);
};
And we only update themessage
property like in the above example, React will replace the original state object:
{ message: '', id: 1 }
With the object used in the onChange
event, which only contains the message property:
{ message: 'message entered' } // id property is lost
You may replicate the behavior of setState() by passing the object to be replaced as a function argument and using the object spread
syntax:
onChange={e => {
const val = e.target.value;
setMessage(prevState => {
return { ...prevState, message: val }
});
}}
The ...prevState
part will get all of the properties of the object and the message: value
part will overwrite the message
property.
You just have to be careful when applying the spread
syntax to multidimensional arrays because it won’t work as you might expect.
This leads us to another thing to consider when working with objects as the state.
Updating state in React hooks: For Nested objects
In JavaScript, multidimensional arrays are arrays within arrays:
[
['value1','value2'],
['value3','value4']
]
You could use them to centralize all of your state variables. However, it is preferable to use nested objects for this purpose:
{
'row1' : {
'key1' : 'value1',
'key2' : 'value2'
},
'row2' : {
'key3' : 'value3',
'key4' : 'value4'
}
}
However, when working with multidimensional arrays and nested objects, the spread
syntax and Object. assign
will create a shallow copy rather than a deep copy.
When copying an array, the spread
syntax essentially goes one level deep. As a result, as the following example shows, it may not be suited for copying multidimensional arrays. (The same is true for spread
syntax and Object.assign()
.)
let a = [[1], [2], [3]];
let b = [...a];
b.shift().shift(); // 1
// Array 'a' is affected as well: [[], [2], [3]]
but the important point is that when using nested objects, we can’t just use the spread syntax to update the state object.
For example, consider the following state object:
const [msgObj, setMsg] = useState({
author: '',
msg: {
id: 1,
text: ''
}
});
The following code snippets show some incorrect ways to update the text field:
// Wrong
setMsg(prevState => ({
...prevState,
text: 'My message'
}));
// Wrong
setMsg(prevState => ({
...prevState.msg,
text: 'My message'
}));
// Wrong
setMsg(prevState => ({
...prevState,
msg: {
text: 'My message'
}
}));
To properly update the text field, we have to copy to a new object the entire set of fields/nested objects of the original object
// Correct
setMsg(prevState => ({
...prevState,
msg: {
...prevState.msg,
text: 'My message'
}
}));
In the same way, here’s how you’d update the author field of the state object:
// Correct
setMsg(prevState => ({
author: 'Joe',
...prevState.msg
}));
Assuming the message object doesn’t change. If it does change, you’d have to update the object this way:
// Correct
setMsg(prevState => ({
author: 'Joe',
msg: {
...prevState.msg,
text: 'My message'
}
}));
Conculsion
useState
is a Hook (function) that enables state variables to be used in functional components. This function takes the initial state and returns a variable with the current state value (not necessarily the starting state) and another function to update it.
Posted on May 19, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
September 19, 2024