React Hooks: useState

Tay Bencardino
5 min readJul 23, 2023
React being caught by a hook — This image was made by me on Canva using React logo.

Today was my first day at Focus Friday at work. It’s the Friday when we all focus on studying and learning more about things we’ve already worked on or learning something new. I chose to learn more about React Hooks. Even though I am with them almost daily at work, I want to understand more about the concepts and rules and why we use them.

I’ve divided this blog into four parts to share some of that with you.

  1. What are React Hooks?
  2. What are the rules for using them?
  3. What is useState?
  4. An example of useState

Before we dive into the world of React Hooks, let’s take a moment to understand the basics of React, a powerful JavaScript library for building user interfaces.

React follows a component-based architecture, dividing user interfaces into smaller, reusable components. These components encapsulate both the UI logic and state, making building and maintaining complex applications easier.

In React, we have two types of components: class components and functional components. Traditionally, class components were used for their ability to hold and manage state. However, with the introduction of React Hooks, functional components have become the preferred choice due to their simplicity and ease of use.

React also introduces the concept of a Virtual DOM, which allows for efficient and optimised updates to the user interface. This ensures that only the necessary parts of the UI are updated when there’s a change in the component’s state, resulting in improved performance.

Throughout this blog, we’ll explore one of the most essential Hooks in React — useState. This powerful Hook enables functional components to have their own state, empowering them to store and update data over time.

What are React Hooks?

Hooks are a new addition to React 16.8, allowing you to use state and other React features. They are functions that will enable you to “hook into” the state and lifecycle of React components from functional components. Basically, they allow you to add React features to functional components.

Some of the most common Hooks include useState, useEffect, useMemo, useCallback. Each of these Hooks allows you to do something different in a functional component. For example, useState allows you to add a state to a functional component while useEffect allows you to perform side effects in a functional component. Today we will only cover the useState Hook.

What are the rules for using them?

It is important to remember that there are some rules for using Hooks. For example, Hooks should only be called at the top level of a component and never inside loops or nested functions. In addition, Hooks can only be called in React functional components or custom Hooks.

Check what the official React Documentation says:

Rule 1: Only call Hooks at the top level “Don’t call Hooks inside loops, conditions, or nested functions. Instead, always use Hooks at the top level of your React function. By following this rule, you ensure that Hooks are called in the same order each time a component renders. That’s what allows React to correctly preserve the state of Hooks between multiple useState and useEffect calls.”

Rule 2: Only call Hooks from React Functions “Don’t call Hooks from regular JavaScript functions. Instead, you can: Call Hooks from React function components. Call Hooks from custom Hooks. By following this rule, you ensure that all stateful logic in a component is clearly visible from its source code.”

What is useState?

This Hook grants functional components the ability to possess a state, enabling them to store and modify data dynamically.

useState stands tall as one of the most indispensable and standard Hooks in the React ecosystem. It empowers functional components with the capability to hold and manage state effortlessly, making it an indispensable tool for building dynamic and responsive React applications.

With useState, you can smoothly slap some state variables onto your functional components. It’s like magic — you can watch changes in the component’s state and make it re-render whenever you want. Having the useState into functional components makes your code clean and readable. It’s a win-win! 🎉

So, let's check an example of useState:

import React, { useState } from "react";
import "./App.css";

const App = () => {
const [content, setContent] = useState({ title: "⭐️ counting ⭐️", count: 0 });
const [emoji, setEmoji] = useState(" ⬅️ ");

const title = content.title;
const count = content.count;

const increase = () => {
setContent((previousValues) => {
return { ...previousValues, count: previousValues.count + 1 };
});
setEmoji(" ⬆️ ");
};

const decrease = () => {
setContent((previousValues) => {
return { ...previousValues, count: previousValues.count - 1 };
});
setEmoji(" ⬇️ ");
};

return (
<div className="App">
<header className="App-header">
<h1>{title}</h1>
<button onClick={increase}>INCREASE</button>
{count}
{emoji}
<button onClick={decrease}>DECREASE</button>
</header>
</div>
);
}

export default App;

At the top level of the App component, two state variables content and emoji are declared using the useState hook. The useState hook returns an array containing the current value of the state variable and a function to update that value.

const [content, setContent] = useState({ title: "⭐️ counting ⭐️", count: 0 });
const [emoji, setEmoji] = useState(" ⬅️ ");

By employing array destructuring syntax, you get the current state value and the function to update it. This makes your code cleaner, more concise, and easier to maintain, encouraging better developer collaboration.

In this code, content is initialized with an object containing two properties: title and count, while emoji is initialized with a string containing an emoji.

const title = content.title;
const count = content.count;

Here we extract the title and count properties from the object state for easier access later in the component.

const increase = () => {
setContent((previousValues) => {
return { ...previousValues, count: previousValues.count + 1 };
});
setEmoji(" ⬆️ ");
};

const decrease = () => {
setContent((previousValues) => {
return { ...previousValues, count: previousValues.count - 1 };
});
setEmoji(" ⬇️ ");
};

These are two functions, increase and decrease, which will be called when the "INCREASE" and "DECREASE" buttons are clicked. They use the setContent function to update the count property of the content state variable by incrementing or decrementing its current value. Additionally, they call the setEmoji function to update the emoji state variable with different emojis based on the button clicked.

This is the output of the App component.

In the end, useState is a total game-changer in React! This powerful Hook makes managing state in functional components a breeze, resulting in cleaner code and better teamwork among devs. The magic of array destructuring simplifies data handling, making our React apps super smooth and maintainable.

Explore other Hooks like useEffect, useContext, and more to take your skills to the next level. Unleash the power of useState and build mind-blowing web apps that your users will love.

Happy coding! 🚀

Resources:

  • Book React 18 Design Patterns and Best Practices — Fourth Edition
  • React Official Documentation — react.dev

--

--