React Hooks: Managing State With useState Hook

Full-Stack Developer, Entrepreneur and Co-Founder of Coderplex.
Building https://coderplex.in
Checkout my portfolio at https://bhanuteja.dev
Search for a command to run...

Full-Stack Developer, Entrepreneur and Co-Founder of Coderplex.
Building https://coderplex.in
Checkout my portfolio at https://bhanuteja.dev
No comments yet. Be the first to comment.
In this series, I will write different blog posts based on workshop content from [Kent C. Dodds](https://kentcdodds.com)'s [EpicReact.Dev](https://epicreact.dev) as I go through it.
Hello World 👋 Hooks are special types of functions in React that you can call inside React functional components. They let you store data, add interactivity, and perform some actions, otherwise known as side-effects. The most common hooks are: useS...
Authored in connection with the Write With Fauna program. Table of Contents Authentication Setting up Fauna in Next.js Installing Fauna Setting up Migrations Tool Authentication and Authorization in Fauna Next.js Serverless Function Setup for Fa...

I wanted to start blogging in Aug of 2020. I decided to use @hashnode for my blog. It was the best decision that I made. I wrote 27 technical articles so far. Most of them are about frontend web development. A thread 🧵 about each of these articles i...

Next.js has become my go-to framework for almost every project that I make. So, I made a starter template that I can just use and get started easily. In this article, I will show you how to use the starter template that I made and deploy it with Verc...

In this article, I will list out all the git commands that I use very frequently. This is not in any way a complete list, just the commands that I use very often. This is intended to be used as a quick reference to perform an action that you want. ...

In this article, we will see the order in which different useEffect callbacks and cleanups happen. We will also see how it differs when the app mounts, unmounts, updates. This image is taken from https://github.com/donavon/hook-flow. I took the ex...

Bhanu Teja Pachipulusu's blog
29 posts
Developer, Indie Maker and Blogger. Currently building MDX.one
Checkout my portfolio
Hooks are special types of functions in React that you can call inside React functional components. They let you store data, add interactivity, and perform some actions, otherwise known as side-effects.
Below are the most common hooks that you use:
In this article, we will learn in-depth about useState hook.
useState is a built-in function in React. It takes a single argument and returns an array of two elements when executed.
Let's see an example.
const [count, setCount] = useState(0)
var and setVar. For instance, in the above example, we named it as count and setCount.In the above example, we called useState with the argument of 0. This means that the initial value of the state is 0. count contains the value of the state. setCount is a function you can use to set the value of count.
Let's see the complete example of a component to get an idea of how useState is used in React.
import React, { useState } from "react"
function Counter() {
const [count, setCount] = useState(0)
function increment() {
setCount(count + 1)
}
return (
<button onClick={increment}>{count}</button>
)
}
This renders a simple button that shows the value of count. Initially, it is 0. Whenever you click on the button, the count value is increased by 1 by using setCount. And as soon as the state changes, the component rerenders and the new value of count is shown in the button.
Let's slightly change the above component.
import React, { useState } from "react"
function Counter() {
const [count, setCount] = useState(0)
function incrementBy3() {
setCount(count + 2)
setCount(count + 1)
}
return (
<button onClick={incrementBy3}>{count}</button>
)
}
Now, when you click on the button, what would you expect the increment to be. Will the count be incremented by 2? (or) Will it be incremented by 1? (or) Will it be incremented by 3?
Click and try it out.
Here is the corresponding code sandbox for it.
You can observe that the count will only be incremented by 1. This is because of how React makes state updates. Many state updates are batched together and performed in an asynchronous manner. So, if you have two setState calls at the same place, you cannot rely on React to complete the first state update before doing the second state update.
Let's take the above example.
count is 0.setCount(count + 2). count in that render is 0. count for the next render to be count + 2, which is 2. 0.setCount(count + 1). count is still 0, React calculates the value of count for the next render to be count + 1 which is 1. setCount(count+2) is executed. Now, it got overridden by the value of next state of setCount(count+1) which is 1.Even though it takes a while to understand the problem that is occurring, the solution to fix this problem is not that complicated.
Till now we have seen that setCount takes a value as an argument. But it also takes a callback as the argument of setCount. The first argument of that callback function is the previous value of the state.
For example, if we want to increment the count by 1, you can do it as follows:
setCount(previousCount => previousCount + 1)
When you use this type of callback function to update the state, you can be assured that the prevCount will always have the correct value of the state even though the component is not yet rerendered. That is why it is always recommended to use this type of update whenever the next value of the state is computed from the previous value of the state.
Let's use this approach and rewrite the above example.
import React, { useState } from "react"
function Counter() {
const [count, setCount] = useState(0)
function incrementBy3() {
setCount(previousCount => previousCount + 2)
setCount(previousCount => previousCount + 1)
}
return (
<button onClick={incrementBy3}>{count}</button>
)
}
This correctly increments the count by 3.
const initialValue = resultOfSomeExpensiveOperation()
const [state, setState] = useState(initialValue)
Previously we have seen that the useState takes the initial value as an argument.
Technically React only needs the initialValue when the component is first mounted. After that, the initialValue is no longer applicable. So if the initial value is calculated through some expensive operations, we want those operations to run only at the start. Let's see if that is actually happening or not through an example.
import React, { useState } from "react";
function getInitialValue() {
console.log('getInitialValue is getting executed');
// ... do some expensive operations
return 0;
}
function Counter() {
const [count, setCount] = useState(getInitialValue());
function increment() {
setCount(count + 1);
}
return <button onClick={increment}>{count}</button>;
}
Try to click on the button and check the console.
getInitialValue function is being executed every time the button is clicked. So, it is getting called on every rerender.getInitialValue is useful for React. All others will be thrown away as the state is already set in the subsequent rerenders.React gives us a way to handle this type of situation. It's called Lazy Initialization of State.
Instead of directly passing the value as an argument, you have the option to pass a callback function which when executed gives you the initial value. React executes this function only when it is needed. This is needed only at the first, so React executes this function only once at the start.
Let's rewrite the above example to use lazy state initialization.
import React, { useState } from "react";
function getInitialValue() {
console.log('getInitialValue is getting executed');
// ... do some expensive operations
return 0;
}
function Counter() {
const [count, setCount] = useState(() => getInitialValue());
function increment() {
setCount(count + 1);
}
return <button onClick={increment}>{count}</button>;
}
All we changed in the above example is that: useState(getInitialValue()) is changed to useState(() => getInitialValue()).
You can check the console of the above code sandbox. You will see that getInitialValue is not getting called when you click on the button. It is only called at the start.
You can manage any type of state with useState hook, even objects.
For example, let's use useState hook to manage firstName and lastName states in a single object.
const [name, setName] = useState({
firstName: 'Bhanu Teja',
lastName: 'P'
})
Now, whenever you call setName to update the name object, you have to provide both firstName and lastName.
For example,
setName({
firstName: 'New First Name',
lastName: 'New Last Name'
})
What if we want to update only the firstName or only the lastName. You can do so by using the spread operator.
function setFirstName(firstName) {
setName({
...name,
firstName
})
}
function setLastName(lastName) {
setName({
...name,
lastName
})
}
Let's put everything together.
import React, { useState } from "react";
function App() {
const [name, setName] = useState({
firstName: "Bhanu Teja",
lastName: "P"
});
function setFirstName(firstName) {
setName({
...name,
firstName
});
}
function setLastName(lastName) {
setName({
...name,
lastName
});
}
return (
<>
<input
placeholder="First Name"
type="text"
value={name.firstName}
onChange={(e) => setFirstName(e.target.value)}
/>
<input
placeholder="Last Name"
type="text"
value={name.lastName}
onChange={(e) => setLastName(e.target.value)}
/>
<p>
Your name is:{" "}
<strong>
{name.firstName}.{name.lastName}
</strong>
</p>
</>
);
}
Usage of useState with arrays is very similar to that of with objects.
You learned about:
useState hook:useState with objects and arrays.In the next article, we will learn everything about useEffect hook.
If this was helpful to you, Please Like and Share so that it reaches others as well. To get email notifications on my latest articles, please subscribe to my blog by hitting the Subscribe button at the top of the page. You can also follow me on Twitter @pbteja1998.