DEV Community

Cover image for 5 use cases of the useState ReactJS hook
Damian Demasi
Damian Demasi

Posted on • Updated on

5 use cases of the useState ReactJS hook

useState is a Hook that needs to be called inside a function component to add some local state to it. React will preserve this state between component re-renders.

There are many use cases for the useState hook, but in this article, I will focus on the following five:

useState use cases

  • State management
  • Conditional rendering
  • Toggle flags (true/false)
  • Counter
  • Get API data and store it in state

State management

Let's start with a warning: don't write code in this way, because it will create an infinite loop:

import { useState } from "react";

const UseCaseStateManagement = props => {
    const [state, setState] = useState('initial value');

    setState('new value');
    console.log(state);

    return (
        <>
            <h2>useState use case</h2>
            <h3>State management</h3>
            <hr />
            <p>{state}</p>
        </>
    );
};

export default UseCaseStateManagement;
Enter fullscreen mode Exit fullscreen mode

The loop is created because the initial render calls the state update function setState, which in time triggers a re-render and a new function evaluation.

If we want to change a state due to an action performed by the user, we can do this:

import { useState } from "react";

const UseCaseStateManagement = props => {
    const [state, setState] = useState('initial value');

    console.log('🔄 This is a re-render');

    const clickHandler = () => {
        setState('new value');
    };

    return (
        <>
            <h2>useState use case</h2>
            <h3>State management</h3>
            <hr />
            <button onClick={clickHandler}>Set state</button>
            <p>{state}</p>
        </>
    );
};

export default UseCaseStateManagement;
Enter fullscreen mode Exit fullscreen mode

That state will be preserved across component re-renders and we will be able to make use of it in the newest re-render.

Conditional rendering

We can use a state to conditionally render a component or part of it.

import { useState } from "react";

const UseCaseConditionalRender = props => {
    const [condition, setCondition] = useState(false);

    const clickHandler = () => {
        setCondition(true);
    };

    return (
        <>
            <hr />
            <h2>useState use case</h2>
            <h3>Conditional Rendering</h3>
            <button onClick={clickHandler}>Set condition</button>
            {condition && <p>Hello!</p>}
        </>
    );
};

export default UseCaseConditionalRender;
Enter fullscreen mode Exit fullscreen mode

Toggle flags

useState can be used to toggle between two values, usually true and false, in order to toggle a flag, such as the display mode:

import { useState } from 'react';
import classes from './UseCaseToggle.module.css';

const UseCaseToggle = props => {
    const [mode, setMode] = useState(false);

    // Use setState function form because the new state depends on the previous one
    const clickHandler = () => {
        setMode(prevState => !prevState);
    };

    const toggledClass = mode ? classes.light : classes.dark;

    return (
        <div className={toggledClass}>
            <hr />
            <h2>useState use case</h2>
            <h3>Toggle flags</h3>
            <button onClick={clickHandler}>Toggle display mode</button>
        </div>
    );
};

export default UseCaseToggle;
Enter fullscreen mode Exit fullscreen mode

The result will be an alternation between dark and light mode on the component.

Counter

useState can be used to keep track of a variable through multiple re-renders, such as in a counter application:

import { useState } from "react";

const UseCaseCounter = props => {
    const [counter, setCounter] = useState(0);

    // Use setState function form because the new state depends on the previous one
    const clickHandlerDecrease = () => {
        // Converting the prevState to number to avoid errors
        setCounter(prevState => +prevState - 1);
    };

    const clickHandlerIncrease = () => {
        setCounter(prevState => +prevState + 1);
    };

    return (
        <>
            <hr />
            <h2>useState use case</h2>
            <h3>Counter</h3>
            <button onClick={clickHandlerDecrease}>--</button>
            <span> {counter} </span>
            <button onClick={clickHandlerIncrease}>++</button>
        </>
    );
};

export default UseCaseCounter;
Enter fullscreen mode Exit fullscreen mode

Get API data and store it in state

A more complex use of this hook is presented when we need to interact with an API. In this case, we can use a state to store the response of a fetch() to the API, and the state of a spinner that will indicate if the data is being fetched.

import { useState } from "react";

const UseCaseApi = props => {
    const [starship, setStarship] = useState('');
    const [isLoading, setIsLoading] = useState(false);

    const clickHandler = async () => {
        setIsLoading(true);

        const response = await fetch('https://swapi.dev/api/starships/10');
        const data = await response.json();
        setStarship(JSON.stringify(data, null, "\t"));

        setIsLoading(false);
    };

    let message = '';
    if (isLoading) {
        message = <p>Getting data... 🚀</p>;
    }

    return (
        <>
            <hr />
            <h2>useState use case</h2>
            <h3>Get API data and store it in state</h3>
            <button onClick={clickHandler}>Get Millennium Falcon data</button>
            <p>{message}</p>
            <pre>{starship}</pre>
        </>
    );
};

export default UseCaseApi;
Enter fullscreen mode Exit fullscreen mode

You can watch all these examples live here.

You can also take a look at the code in this repository.

Latest comments (7)

Collapse
 
reisogawa profile image
Rei-Sogawa

Thanks for a good article!
I like reducer concept.

Collapse
 
joeattardi profile image
Joe Attardi

You can also use them to store an element ref!
Using a ref is handy but as you probably know, changes to ref.current will not re-render the component.

What if you want it to?

You can use a function ref!

It looks like this:

const [popup, setPopup] = useState();
Enter fullscreen mode Exit fullscreen mode

Then in your JSX:

<div ref={setPopup}></div>
Enter fullscreen mode Exit fullscreen mode

If you aren't familiar with this usage of a ref, a function ref gets called with the element. When the element is removed from the DOM, it is called again and passed null.

You can reference the DOM element now via the popup property (not popup.current as this isn't a "standard" ref.

It can be useful!

Collapse
 
colocodes profile image
Damian Demasi

Wow, nice trick! Thanks!

Collapse
 
adminnrj profile image
admin-nrj

Thank you, don't stop on this one hook, we wait for articles about other hooks. It is very useful information.

Collapse
 
colocodes profile image
Damian Demasi

I'm actually working on the use cases of other hooks as well, so stay tuned! 😉

Collapse
 
maitrungdong profile image
Mai Trung Đông • Edited

I did work all almost these use cases. This post helped me overview this things. Thank you so much 💯

Collapse
 
colocodes profile image
Damian Demasi

Thank you! I'm glad you find it helpful. 😄