Understanding useState in ReactJs

Understanding useState in ReactJs

Hello, fellow Reactêrs!! Welcome to the second article in our series on React. If you haven't read the first article on props, we recommend doing so since useState builds on the concepts covered in that article. In this article, we'll introduce useState, a powerful React hook that allows you to manage state in functional components.

Introduction: What is useState in React?

Before I dive deep into explaining the meaning of useState, I'd like to ask you some questions. Before you started learning React, I'll assume that you had already learned JavaScript or TypeScript. And when building those beautiful websites, you definitely added some interactivity, right? For example, you might have added interactivity to your navigation section on mobile screens, where a hamburger icon appears while the links are displayed as a flexbox on larger screens. Or perhaps you've added onClick events to buttons that open a modal or change the text and color of a paragraph. Let's take an even simpler example: the increment and decrement buttons that are very common on shopping websites. You need to click on the increment button to increase the quantity of your product, or the decrement button to decrease it.

<!DOCTYPE html>
<html>
<body>

<h1 class="product-quantity">0</h1>

<button onclick="increment()">Increase</button>

<button onclick="decrement()">Decrease</button>

<script>
const productQuantity = document.querySelector(".product-quantity");

let count = 0;
const increment = () => {
    count++;
      productQuantity.textContent = count;
}

const decrement = () => {
  count--;
  productQuantity.textContent = count;
}
</script>

As you can see from the code above, we have an increment and decrement button. Two functions were created and added to the buttons onClick event and when that event happens, they affect the textContent of the h1 element. It's as easy as that. But in React, it is done differently. At first glance, using useState in React might seem challenging, but it's actually simpler than the equivalent JavaScript implementation.

In React, you cannot use DOM manipulation methods like querySelector or getElementById to update the state of an element in React. The example above shows how this can be done in plain JavaScript, but React requires a different approach. The state, which in this case is the textContent of the h1 element is being changed on onClick event. In order to make something like this work, we'd need to use a react Hook called useState.

The complicated definition of useState is that useState() is a React Hook that allows you to create, track and update a state in functional components. In simple terms, useState gives you the ability to be able to affect, change and update the state of a component. Remember that components are basically functions that always return an element. This React Hook is what you'd need to use if you want to display your navigation links when you click a hamburger button or if you'd like to have a modal display onclick of a button or even the increment and decrement buttons that affect another element.

Why is state important in building React applications?

State is very important in React because it gives you the ability to manage and store your data and remember data changes a lot of times. You can also refer to state in this case as a variable. Remember that in React, the user interface is broken into small reusable components that have their own functionality and data. Each of those data is stored in a state and whenever the data changes, the state changes too which React will then automatically update the component and any child component that uses that state without you needing to refresh the page.

Let's take a closer look at our example code for the increment and decrement buttons from earlier. In React, changing the value of the h1 element using state is incredibly simple. All you need to do is save the current state of the value and update the state whenever a button is clicked.

In contrast, using JavaScript like in the example above, you would need to select the element that would be affected by the click event, select the two buttons, create a variable to store the initial state or value, and finally create the two functions. That's a lot of work!

But with useState in React, managing state becomes incredibly easy. Instead of all those steps, you simply call the useState hook and pass in the initial state value. useState then returns an array with two elements: the current state value and a function to update that value.

So, with useState, you can easily implement interactive features like increment and decrement buttons that affect another element's state. Overall, useState is a powerful tool that simplifies state management in React and makes it easy to build dynamic and interactive user interfaces.

How to use useState in a React component

The concept of useState is very easy to understand especially if you're very proficient in the ES6 modules of JavaScript. The syntax for useState is very easy too.

    const [count, setCount] = useState(0);

Does this syntax look familiar to you? I'm sure you're thinking right now that yes it does, but probably you can't remember where you've seen or if you've used it. For those very conversant with the ES6 JavaScript syntax, you'll know what I'm going to say next. Well, this syntax is the ES6 way of destructuring an array. The first element in the array is the initial state value which in this case is 0. This means that at the initial state or at the first render of the DOM, the count value is 0 count = 0. While the second element is the state function. This is where we can pass in an argument to update the initial state value.

Let's say we want to update the state value to 5 on click of a button, we would pass in the value as an argument and put the setCount function as the callback function onclick of the button.

import { useState } from "react"

const UseState = () => {
    let [count, setCount] = useState(0);

  return (
    <>
        <h1>Current count is: {count}</h1>
        <button onClick={() => setCount(5)}>
            Click me
        </button>
    </>
  )
}
export default UseState

This is the count of h1 before the button is clicked. When we click the button, the value of the h1 is updated accordingly to the current count value which is 5.

So let's implement the increment functionality that was done with JavaScript at the beginning of this article.

import { useState } from "react"

const UseState = () => {
    let [count, setCount] = useState(0);

    const increment = () => {
        count ++;
        setCount(count);
    }

  return (
    <>
        <h1>Current count is: {count}</h1>
        <button onClick={() => increment()}>
            Click me
        </button>
    </>
  )
}
export default UseState

What we just did was create a function and increment the count by 1 whenever the button is clicked.

Using useState with different data types

You can pass in different data types as an argument to useSatate. It does not only accept numbers. You can pass in strings, boolean, arrays, and objects.

Using useState with strings

You can decide to pass in a string as the argument for the useState. There are different scenarios for this, let's use a loader button as an example. You can use useState to change the textContent to indicate that the button is loading.

import { useState } from "react"

const UseState = () => {
    let [loading, setLoading] = useState("Click me");

  return (
    <>
        <h1>Current count is: {count}</h1>
        <button onClick={() => setLoading("Loading")}>
            {loading}
        </button>
    </>
  )
}
export default UseState

When the button is clicked, the text changes to Loading.

Using useState with booleans

Most React developers use the boolean method if they want to display their navigation links on click of the hamburger button. They set the initial toggle value to false and onClick of the button, they negate the initial value which will toggle the boolean to true or false. Implementing that would be too complicated for this article so we're just going to be adding some styles to some elements onClick.

h4{
    text-align: center;
    font-weight: 700;
}

button{
    border-radius: 15px;
    padding: 8px 20px;
    text-align: center;
}

.text-center{
    text-align: center;
}

.h4-not-coloured{
    color: navy;
}

.h4-coloured{
    color: hotpink;
}

.not-loading-btn{
    background-color: #1fc6ac;
    color: white;
}

.loading-btn{
    color: white;
    background-color: grey;
}

These are the styles to be applied for when the button has not been clicked and when it has.

import { useState } from "react"
import '../index.css'

const UseState = () => {
    const [color, setColor] = useState(false);

    const textColor = color ? "h4-coloured" : "h4-not-coloured";
    const btnColor = color ? "loading-btn" : "not-loading-btn";
    const btnText = color ? "Text color changed" : "Change text color";

  return (
    <>
      <h4 className={textColor}>Hey there! Welcome to useState in React</h4>
      <div class="text-center">
        <button className={btnColor} onClick={() => setColor(!color)}>
          {btnText}
        </button>
      </div>
    </>
  )
}
export default UseState

From the code snippet above, the objective is to change the color of the button, the text content of the button, and the color of the h4 element when it is clicked.

The first thing we do is that we set the initial color to false. Then we create three ternary operators. One to change the h4 text color, another for the button color, and then the button text. We're checking if the color is true. If the condition is true, then the first statement runs else, the second runs. And we save the values of the ternary operators to variables. Then we put the variable in classname for both the button and h4 since we want to change the class. Then to change the text of the button, we put the variable inside of the button's textContent.

In order for these changes to occur, we would need to find a way to toggle the state of color which we do by negating the color variable inside of the state function setcolor. This is because every time the click event occurs, it checks against the previous state and sets it to the opposite of that and since our initial state is false, it will change to true.

Before button click

Before button click

After the button is clicked.

Using useState with arrays

In this example, we're going to implement a kind of add items to cart. in such a way that when a button is clicked, an item gets added to the previous items which is then displayed on the browser.

import { useState } from "react"
import '../index.css'

const UseState = () => {
  const [items, setItems] = useState([]);

  const addToCart = () => {
    setItems([...items, `Item ${items.length + 1}`]);
  }

  return (
    <div className="text-center">
      <button onClick={addToCart}>Add Item</button>
      <ul>
        {items.map((item, index) => (
          <li key={index}>{item}</li>
        ))}
      </ul>
    </div>
  );
}
export default UseState

We first set the initial state of the cart which is going to be empty, that's why we have an empty array there. If you console.log(items) at this point, it would give you an empty array. Then we create a function called addTocart and inside the function, we update the state function. Remember we had an empty array and that this function is to be called when the button is clicked. So we use a spread operation to spread whatever elements we had inside of the array before and we also add a new element Item ${items.length + 1} . What this does is that it checks the length of the array, adds 1 to it, and appends it to the Item string . This would return either Item 1, Item 2 , etc.

Now add the function to the onClick event in the button. Next, we map through the items array and append the li element every time the button is clicked and the textContent is the value inside of the array. Remember when I mention Item 1, Item 2 etc, that is what is going to be the textcontent of the li elements. Then we set the key to the index since it's going to be unique for every item.

No list item is going to display at first because our array is empty.

When you keep clicking on the button, the li elements keep increasing.

Using useState with objects

We're going to change the email of the properties in an object. This is to show that objects can be used directly with useState

import { useState } from "react"
import '../index.css'

const UseState = () => {
  const [person, setPerson] = useState({
    name: 'John Doe',
    age: 30,
    email: 'johndoe@example.com',
  });

  const handleUpdateEmail = () => {
    setPerson({
      ...person,
      email: 'newemail@example.com',
    });
  }
  const {name, age, email} = person;
  return (
    <div>
      <p>Name: {name}</p>
      <p>Age: {age}</p>
      <p>Email: {email}</p>
      <button onClick={handleUpdateEmail}>Update Email</button>
    </div>
  );
}
export default UseState

We, first of all, set the initial value to an object with different key value and then we create the handleUpdateEmail function that would be called onClick of a button. Inside the function, we update the state function setPerson by using the spread operator to expand all the other properties and then we change the value of the email. Before the return statement, we spread the object and get each of its values and those values are set to the textContent of the elements. The handleUpdateEmail function is called anytime the button is clicked.

Before the button is clicked.

After the button is clicked. Notice that the email changes.

Conclusion

If you want your React applications to be functional and interactive, understanding the principles of State is very important. In this article, we have covered a lot of things about useState. We talked about what useState is in React and why it is important. We've also discussed how to use useState in React with different data types such as numbers, strings, boolean, arrays and objects.

I hope you enjoyed reading this article as much as I enjoyed writing it, and even more. Keep learning and building with React!