useState
The signature for the useState
Hook is as follows:

Here, state
and setState
refer to the state value and updater function returned on invoking useState
with some initialState
.
Itβs important to note that when your component first renders and invokes useState
, the initialState
is the returned state from useState
.
Declare State Variable
Always remember that the value of the state is always the initial state value on the first render
const [state] = useState(100)
return <div> State variable is {state}</div>
Update State Variable
Also, to update state, the state updater function setState
should be invoked with a new state value, as shown below:

By doing this, a new re-render of the component is queued. useState
guarantees that the state
value will always be the most recent after applying updates.

For referential checks, the setState
functionβs reference never changes during re-renders.
Here an example of a Counter component that use useState
to update the counter by one for each click
const Counter = () => {
const [counter, setCounter] = useState(0)
const handleClick = () => setCounter(counter + 1)
return (
<div>
Counter:{counter}
<div>
<button onClick={handleClick}>add to the counter </button>
</div>
</div>
)
}
Functional updates
The state setter function returned by useState
can be invoked in two ways. The first is by passing a new value directly as an argument:
const [state, setState] = useState(initialStateValue)
// update state as follows
setState(newStateValue)
This is correct and works perfectly in most cases. However, there are cases where a different form of state update is preferred: functional updates.
Hereβs the example above revised to use the functional update form:
const [state, setState] = useState(initialStateValue)
// update state as follows
setState((previousStateValue) => newValue)
When your new state depends on the previous state value β e.g., a computation β favor the functional state update. Since setState
is async, React guarantees that the previous state value is accurate.
Hereβs an example:
const Counter = () => {
const [count, setCount] = useState(0);
return (
<>
<p>Count value is: {count}</p>
<button onClick={() => setCount(0)}>Reset</button>
<button
onClick={() => setCount(prevCount => prevCount + 1)}>
Plus (+)
</button>
<button
onClick={() => setCount(prevCount => prevCount - 1)}>
Minus (-)
</button>
</>
);
}
In the example above, the button grows every time itβs clicked. Since the new state value depends on the old, the functional update form of setState
is preferred.
Lazily initializing state
The initialState
argument to useState
is only used during your initial render.

// subsequent prop updates are ignored
const App = ({myProp}) => {
const [state, setState] = useState(myProp)
}
// only the initial myProp value on initial render is passed as initialState. subsequent updates are ignored.
Initialize state from function
If the initial state is a result of an expensive computation, you could also pass a function, which will be invoked only on initial render:
const [state, setState] = useState(() => yourExpensiveComputation(props))
As opposed to just passing an initial state value, state could also be initialized from a function, as shown below:
const Component = () => {
const [token] = useState(() => {
// this will only render in first initial render
const token = window.localStorage.getItem("sensetive-data");
return token || "please don't put sensetive data in local storage π’π’π’π’"
})
return <div>Token is {token}</div>
}
Use with objects
As opposed to strings and numbers, you could also use an object as the initial value passed to useState
.
Note that you have to pass the entire object to the useState
updater function because the object is replaced, not merged.This is very different from how this.setState
worked in classes!
function Component() {
const [state, setState] = useState({ name: "Mayssa" });
const updateState = () => setState({ occupation: "Teacher" });
return (
<>
<pre>{JSON.stringify(state)}</pre>
<button onClick={updateState}>update state</button>
</>
);
}
So in order to add an property to the object, weβre using the ES6 spread operator ...
to copy the existing properties into the new object,
const updateState = () => { setState((prevState) => ({ ...prevState, occupation: "Teacher" })); };
Pass a function to setState
and return a merged object by using the spread operator (Object.assign
also works).
Use with arrays
Remember: state can hold any kind of value! Hereβs an example of useState holding an array.
Typing into the box and hitting Enter will add an item to the list.
function ListOfThings() {
const [itemsList, setItemsList] = useState([]);
const [itemName, setItemName] = useState("");
const addItem = event => {
event.preventDefault();
setItemsList([
...itemsList,
{
id: itemsList.length, // just for the sake of the example , never put the index of the item in the array as an id
name: itemName
}
]);
setItemName("");
};
return (
<>
<form onSubmit={addItem}>
<label>
<input
name="item"
type="text"
value={itemName}
onChange={e => setItemName(e.target.value)}
/>
</label>
</form>
<ul>
{itemsList.map(item => (
<li key={item.id}>{item.name}</li>
))}
</ul>
</>
);
}
Notice weβre calling useState with an initial value of an empty array []
,
Such as objects, in order to add an item to the array, weβre using the ES6 spread operator ...
to copy the existing items into the new array, and inserting the new item at the end.
Multiple calls to useState
If you want to store multiple values in a function component, youβve got a couple options:
call
useState
more than onceshove everything into an object
Thereβs nothing wrong with calling useState
multiple times, and in most cases, thatβs how I store multiple values. Once you get over 4 or 5 useState calls it gets a bit unwieldy, but if youβre fine with it, React is too.
Multiple state variables may be used and updated from within a functional component as shown below:
const Component =() => {
const [age, setAge] = useState(19)
const [siblingsNum, setSiblingsNum] =
useState(10)
const handleAge = () => setAge(age + 1)
const handleSiblingsNum = () =>
setSiblingsNum(siblingsNum + 1)
return (
<div>
<p>Today I am {age} Years of Age</p>
<p>I have {siblingsNum Multiple state variables may be used and updated from within a functional component as shown below:} siblings</p>
<div>
<button onClick={handleAge}>
Get older!
</button>
<button onClick={handleSiblingsNum}>
More siblings!
</button>
</div>
</div>
)
}
If expensive calculations are done within the body of your functional component, i.e., before the return statement, consider optimizing these with useMemo
.(we will cover useMemo in another section)
References and articles :
Last updated
Was this helpful?