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
useStatehook - How to update
statein your application , and some rules in using theuseStatehook
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
userMsgwhich we will callstatevariable (for now) - We then assign some value to the
userMsg - In our JSX template, we output the information stored in the
userMsglike 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
userMsgon 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 HookstoLesson one: React useState Hookwhen a user clicks on theGet Startedbutton.We declared a function
handleUserMsg, which will responsible for updating the value when we click on theGet Startedbutton.The
handleUserMsgfunction will be invoked, and in the body of the function, we will assign the new value. to theuserMsgvariable.
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
handleUserMsgfunction is invoked, andLesson one: React useState Hookis now assigned to theuserMsgvariable. - 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 Hookto theuserMsgvariable when thehandleUserMsgfunction is executed. - When the
handleUserMsgfunction 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 thehandleUserMsgfunction, 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
userMsgvariable 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 Hookson 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 variablesin 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
setterresponsible 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
userMsgvariable - The setter function which is responsible for updating the current state will be stored in the
setUserMsgvariable. - 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
useStatehook is responsible for updating the state in react component.
- Anytime we want to update state in React, we should use the
setterfunction, 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
setterfunction 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
setUserMsgfunction, and then pass it the new value we want theuserMsgto store.
See the code below:
const handleUserMsg = () => {
//updating the state variable
setUserMsg("Lesson one: React useState Hook");
};
- The
setUserMsghas 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
setterfunction 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
userNameandpostsstate 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
userDetailsstores anobject{...} - In our JSX template we can access the object
valuesusing the respectivekeyEg.{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
objectcalleduserDetails. - We accessed the data stored in the
userDetailsobject using thekey:valuepair in JavaScript. - Our UI will then show the data needed.
- If we want to update the data, we will use the
setUserDetailsfunction, 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
countstate variable initialized to0 - When we click on the
Count mebutton, 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 thecountandsetCountvariables - The inital state value
0is stored in thecountvariable - The
setCountwhich is thesetterfunction will update thecountvalue - In our JSX template, we display the
countvalue like{count}. - When the component re-renders we will see the value
0on the screen.
- To update the
countvalue based on the previous value, we need to pass an updater function to thesetCount - The
updaterfunction takes theprevious stateand 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 + 1is theupdaterfunction. It is acallbackfunction we passed to thesetterfunction. - When the
setCountfunction is executed, it will evaluate the expression passed as arguments - In the expression, we access the current
count, increase it value by1and returns the value - So if the current
counthas 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
updaterfunction to thesetterfunction.
- Clicking on the
count mebutton, we call thehandleCountfunction. - In the
setCountputs thecallbackorupdaterfunction in a queue. - During the next render, it wil call the
updaterfunction take the previous value ofcount, and add1to it ,count + 1, and returns the **updated **value. - On the next click on the button, the
current statevalue is now1, and we add1to 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 + 1will receive0as the initial state and return1as the next state -
count => count + 1will receive1as the previous state and return2as the next state -
count => count + 1will receive2as the previous state and return3as 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
useStatehook to track, update and manage states in function components - The
state variablecan be of anydata type(strings,numbers,boolean,objects) - The call to the
useState(initialState)hook returns two values, theinitalStateand asetterfunction - To update the state use the
setterfunction - 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)
Top comments (0)