Table of contents
- Understanding State in React
- Using State in a component
- Displaying the state in our UI
- Changing State In React.
- Re-rendering component when state changes.
- Exploring "reactivity" in regular variables
- States Should be Reactive
- Updating a component with new data.
- What is the useState hook ?
- Updating the State using the Setter function
- Adding multiple state variables to the component
- Using Objects as State variables
- Updating the state based on previous state
- Where to call the useState() hook
- Recap
Hello World, in this article, we take a dive on how to manage states in our React application using the useState
hook.
By the time you finish reading the article, you should be able to
- Understand
state
- How to implement the
useState
hook - How to update
state
in your application , and some rules in using theuseState
hook
Let's get started.
Understanding State in React
State is data or value that is subject to change in our application. It describes the condition of our app at any point in time.
Because we build dynamic web apps in React, we will expect the data (information) in our app to change in response to a user's action. These actions could be a user:
- Clicking on a button
- Entering a value in a form field
- Submitting a form.
- Clicking on the next button on an image carousel.
Anytime state
(data or information) changes in React, the component will re-render and display the updated information on the screen as a result of the above interactions.
State can be of any data type, it can be an object
, array
, a string
, boolean
etc.
The code below demonstrate how to use state in a component.
Using State in a component
import React from "react"
import "./styles.css";
export default function App() {
// defining a regular variable
const userMsg = "Start learning React Hooks";
return (
<div className="App">
<h1>Hello User</h1>
<h2>{userMsg}</h2>
<button>Get Started </button>
</div>
);
}
In the code above:
- We defined a "regular" variable
userMsg
which we will callstate
variable (for now) - We then assign some value to the
userMsg
- In our JSX template, we output the information stored in the
userMsg
like this{userMsg}
- Doing this, we preserve the (state) value between function calls. Anytime the app reloads, we will still see the value stored in the
userMsg
on the screen.
Displaying the state in our UI
With the code above, when we launch our app we should see the below on our screen:
Hello User
Start learning React Hooks
Changing State In React.
We usually want the state (data or information) on the UI to change when an event occurs on the app. For instance, a user clicking on a button.
Let's take a look at how to change the state in our app.
We want the state (value or data ) to change from
Start learning React Hooks
toLesson one: React useState Hook
when a user clicks on theGet Started
button.We declared a function
handleUserMsg
, which will responsible for updating the value when we click on theGet Started
button.- The
handleUserMsg
function will be invoked, and in the body of the function, we will assign the new value. to theuserMsg
variable.
See the code below
import React from "react";
import "./styles.css";
export default function App() {
// defining a regular variable
const userMsg = "Start learning React Hooks";
const handleUserMsg = () => {
// assigning a new value to the variable
userMsg = "Lesson one: React useState Hook"
};
return (
<div className="App">
<h1>Hello User</h1>
{/* using the state */}
<h2>{userMsg}</h2>
<button onClick={handleUserMsg}>Get Started</button>
</div>
);1
}
What is happening in the code above:
- On the click of the "Get Started" button, the
handleUserMsg
function is invoked, andLesson one: React useState Hook
is now assigned to theuserMsg
variable. - With that, we have updated the value (this is how we learnt to assign a new value to a variable in JavaScript)
Re-rendering component when state changes.
When we assign a new value to our state
variable in React, our app will need to reload (re-render) to display the updated data (information).
In the code above:
- We assigned
Lesson one: React useState Hook
to theuserMsg
variable when thehandleUserMsg
function is executed. - When the
handleUserMsg
function is invoked, the state (data or value has changed), and we will expect the browser to re-render to output the code below on the user interface:
Hello User
Lesson one: React useState Hook
Note: But it does not, let's find out why in the next section.
Exploring "reactivity" in regular variables
Even though we expect the browser to output the latest data, assigned to the userMsg
variable, clicking the Get Started
button does not update the state (data) from Start learning React Hooks
to Lesson one: React useState Hook
.
We can actually prove the new State Lesson one: React useState Hook
was assigned to userMsg
console.log(userMsg)
in thehandleUserMsg
function, as illustrated in the code above
The handleUserMsg()
event handler is updating the regular variable userMsg
. However, the change is not visible due to the below:
- The
userMsg
variable declared above, is considered a "regular" variable, and "regular" variables do not carry on between renders. - When the component is rendered again, it does not consider any new value assigned to the regular variables.
- Hence, any update to "regular" variables won't trigger renders (React doesn't realize it needs to render the component again with the new value).
States Should be Reactive
The value stored in the userMsg
variable has changed, but the change is not reflecting on the user interface.
This is because the value stored in the userMsg
variable is only a regular variable and not reactive.
What this means is:
- React does not track the regular variable for changes
- When the value changes, it will not trigger React to re-render the component to reflect the update.
- Hence, we continue to see the initial value
Start learning React Hooks
on the user interface.
Updating a component with new data.
To update a component with the new data, we need to make the value 'reactive'.
The below need to happen:
- Retain the data between renders
- Cause React to render the component with new data (re-rendering)
To update the component with new data, we need to rely on the useState
hook. It will provide these two things:
- First is a state variable to retain the data between renders
- Secondly, a setter function to upate the variable and trigger React to render the component again.
Using the useState
hook, React can track the changes in the value, by comparing the new value to the initial value.
Let's now make our state reactive using the useState()
hook.
What is the useState hook ?
The useState() hook enables you to add
state variables
in functional components. It allows developers to track changes, update and manipulate state inside functional components without needing to convert it to a class component.
Syntax for the useState hook
The syntax for the useState
hook is as below
const [state, setState] = useState(initialState)
How to use the useState
hook
In order to use the useState()
hook, we need to import it from react
library like the below
import React,{useState} from "react";
- Now that we have imported the
useState()
hook, we can use it in our functional component and pass it a reactive value. - The reactive value is the initial value or initial state you want to display on the user interface.
In code below, we call the useState
hook and pass it our initial state
... = useState("Start learning React Hooks");
Below is the complete code, let's break it down further:
import React, { useState } from "react";
import "./styles.css";
export default function App() {
//calling the useState hook and passing the initial value
const [userMsg, setUserMsg] = useState("Start learning React Hooks");
//function to change the state
const handleUserMsg = () => {
//update the state inside this function's body
};
return (
<div className="App">
<h1>Hello User</h1>
<h2>{userMsg}</h2>
<button onClick={handleUserMsg}>Get Started</button>
</div>
);
}
Under the hood of useState hook
When the useState()
hook is called like this : useState("Start learning React Hooks")
, it returns an array with two values:
- First, is the initial state value
- Next, a function called the
setter
responsible for updating the current state
We then use array destructuring
in JavaScript to store the values returned by calling the useState()
function into distinct variables: userMsg
and setUserMsg
.
const [userMsg, setUserMsg] = useState("Start learning React Hooks");
In the code above:
- The initial state is stored in the
userMsg
variable - The setter function which is responsible for updating the current state will be stored in the
setUserMsg
variable. - The variable names is entirely up to you. By convention, we name state variables like
[someState, setSomeState]
.
Reading the state variable
The initial value stored in the userMsg
variable can be read . We use it in our JSX template like {userMsg}
import React, { useState } from "react";
import "./styles.css";
export default function App() {
// defining a user message state
const [userMsg, setUserMsg] = useState("Start learning React Hooks");
//function to change the state
const handleUserMsg = () => {};
return (
<div className="App">
<h1>Hello User</h1>
{/* using the state */}
<h2>{userMsg}</h2>
<button onClick={handleUserMsg}>Get Started</button>
</div>
);
}
- Now anywhere we use the
{userMsg}
state in our template, we will expect to output the initial valueStart learning React Hooks
Updating the State using the Setter
function
The setter function returned by the
useState
hook is responsible for updating the state in react component.
- Anytime we want to update state in React, we should use the
setter
function, and not update the state directly. - Meaning, we can not assign a new value to a variable in React, and expect the new value to reflect on the UI. We will need to use the
setter
function to assign a new value.
Referencing the code above, when we click on the Get Started
button, the handleUserMsg
event handler function will be executed.
In the handleUserMsg
function's code block, we will now update the state by doing the below:
- We will call the
setUserMsg
function, and then pass it the new value we want theuserMsg
to store.
See the code below:
const handleUserMsg = () => {
//updating the state variable
setUserMsg("Lesson one: React useState Hook");
};
- The
setUserMsg
has now updated the value stored inuserMsg
Now, when we click the Get Started
button, the handleUserMsg
function will be executed, and in the function's body, we update the value stored in the userMsg
. Since a new value has been assigned to the userMsg
variable, the component will re-render and the browser will display the new value Lesson one: React useState Hook
The UI will display the below:
Hello User
Lesson one: React useState Hook
Below is the updated code:
import React, { useState } from "react";
import "./styles.css";
export default function App() {
// defining a user message state
const [userMsg, setUserMsg] = useState("Start learning React Hooks");
//function to update the state
const handleUserMsg = () => {
//updating the state variable
setUserMsg("Lesson one: React useState Hook");
};
return (
<div className="App">
<h1>Hello User</h1>
{/* using the state */}
<h2>{userMsg}</h2>
<button onClick={handleUserMsg}>Get Started</button>
</div>
);
}
Now using the useState
hook , we can achieve the following:
- Decide which data or information to display on the UI
- Update that data or information using the
setter
function provided by theuseState()
hook.
Adding multiple state variables to the component
More than one state (data or information) of as many data types
can be added to our component using multiple useState()
calls. This helps us to display vital information on the user interface of our app.
To acheive that, use the syntax below:
function MyComponent() {
const [state1, setState1] = useState(initial1); // first state
const [state2, setState2] = useState(initial2); // second state
const [state3, setState3] = useState(initial3); // third state
// ...
}
Let's display multiple data or information (state) in our app.
import React, { useState } from "react";
import "./styles.css";
export default function App() {
// adding multiple states
const [userName, setUserName] = useState("Emmanuel");
const [posts, setPosts] = useState(7);
const [showPosts, setShowPosts] = useState(false);
return (
<div className="App">
{/* using the userName state */}
<h1>Hello {userName}</h1>
{/* using the posts state */}
<p>You have {posts} articles published </p>
</div>
);
}
The output of the code will be
Hello Emmanuel
You have 7 articles published
- In the code above, we have display information about the user , and the number of posts published.
- It is a good practice to have multiple state variables, if the state is unrelated.For instance, the
userName
andposts
state variables are unrelated, so we create multiple state variables. - If the state variables are related, it will be a good idea to put them in an
object
.
Using Objects as State variables
The state variable can be of any data
type. So far, we have used a string
and a number
as state variables.
Let's take a look at using object
as state variables.
import React, { useState } from "react";
import "./styles.css";
export default function App() {
//using objects as state variables.
const [userDetails, setUserDetails] = useState({
fullName: "Emmanuel Kumah",
title: "Frontend Developer",
location: "Ghana",
bio: "Helping you understand everyline of code"
});
return (
<div className="App">
<h1>Profile </h1>
<p>
<strong>Name:</strong>
{userDetails.fullName}
</p>
<p>
<strong>Title:</strong>
{userDetails.title}
</p>
<p>
<strong>location</strong>
{userDetails.location}
</p>
<p>
<strong>Bio</strong>:{userDetails.bio}
</p>
</div>
);
}
- The
userDetails
stores anobject
{...}
- In our JSX template we can access the object
values
using the respectivekey
Eg.{userDetails.fullName}
The output of the above will be:
Profile
Name:Emmanuel Kumah
Title:Frontend Developer
location: Ghana
Bio:Helping you understand everyline of code
- All our data was stored in an
object
calleduserDetails
. - We accessed the data stored in the
userDetails
object using thekey:value
pair in JavaScript. - Our UI will then show the data needed.
- If we want to update the data, we will use the
setUserDetails
function, and update the respective value.
Updating the state based on previous state
Often, we want to update the state by relying on the value of the previous state.
For instance:
- We have a
count
state variable initialized to0
- When we click on the
Count me
button, we want to count the number of times the button has been clicked. - To achieve this, we need access to the previous count to increase it by one.
Let's see an example
import React, { useState } from "react";
import "./styles.css";
export default function App() {
const [count, setCount] = useState(0);
// function to increase count
const handleCount = () => {
//updating the state based on previous value
setCount((count) => count + 1);
};
return (
<div className="App">
{/* using the count state */}
<p>You have clicked the button {count} times</p>
<button onClick={handleCount}>Count me</button>
</div>
</div>
);
}
What is happening in the code above:
- The
useState()
hook was called, and passed the initial value of0
. - The two values returned by calling the
useState(0)
is stored in thecount
andsetCount
variables - The inital state value
0
is stored in thecount
variable - The
setCount
which is thesetter
function will update thecount
value - In our JSX template, we display the
count
value like{count}
. When the component re-renders we will see the value
0
on the screen.To update the
count
value based on the previous value, we need to pass an updater function to thesetCount
- The
updater
function takes theprevious state
and evaluates thenext state
.
Below is the function to update the state
// function to increase count
const handleCount = () => {
setCount((count) => count + 1);
};
- Take note of the
setCount((count) => count + 1)
- The
(count) => count + 1
is theupdater
function. It is acallback
function we passed to thesetter
function. - When the
setCount
function is executed, it will evaluate the expression passed as arguments - In the expression, we access the current
count
, increase it value by1
and returns the value - So if the current
count
has a value of0
, on the first click of the button, the value is updated to1
.
Whenever, you want to update the state based on value in the previous state, remember to pass the
updater
function to thesetter
function.
- Clicking on the
count me
button, we call thehandleCount
function. - In the
setCount
puts thecallback
orupdater
function in a queue. - During the next render, it wil call the
updater
function take the previous value ofcount
, and add1
to it ,count + 1
, and returns the updated value. - On the next click on the button, the
current state
value is now1
, and we add1
to the current state, returning a next value of2
.
This is what is happening when we click on the count me
button 3 times.
// function to increase count
const handleCount = () => {
setCount((count) => count + 1); // setCount(0 => 1);
setCount((count) => count + 1); // setCount(1 => 2);
setCount((count) => count + 1); // setCount(2 => 3);
};
count => count + 1
will receive0
as the initial state and return1
as the next statecount => count + 1
will receive1
as the previous state and return2
as the next statecount => count + 1
will receive2
as the previous state and return3
as the next state
Where to call the useState()
hook
Be aware of the following rules when using useState()
hook:
- Do not use
useState()
in loops, conditions, nested functions , etc - Use only
useState()
inside functional component or a custom hook - Call the
useState()
hook at the top level of the component.
Recap
In conclusion:
- In React app, it is a bad practices to update states variables directly like we do in JavaScript
- We should use the
useState
hook to track, update and manage states in function components - The
state variable
can be of anydata type
(strings
,numbers
,boolean
,objects
) - The call to the
useState(initialState)
hook returns two values, theinitalState
and asetter
function - To update the state use the
setter
function - When the state is updated, the component will re-render to show the updated state (data) in our UI
- You can have multiple state variables in your component.
Thanks for taking time to read my article. If you find this article, useful, kindly share it on your social media pages. Any comment or suggestion on the article will be appreciate.
Written wth love from Ghana. Me daa se (Thank you)