Damian Demasi
Damian Demasi's Blog

Damian Demasi's Blog

5 use cases of the useState ReactJS hook

5 use cases of the useState ReactJS hook

Damian Demasi's photo
Damian Demasi
ยทSep 16, 2021ยท

4 min read

Subscribe to my newsletter and never miss my upcoming articles

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;

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;

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;

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;

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;

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;

You can watch all these examples live here.

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


๐Ÿ—ž๏ธ NEWSLETTER - If you want to hear about my latest articles and interesting software development content, subscribe to my newsletter.

๐Ÿฆ TWITTER - Follow me on Twitter.

Did you find this article valuable?

Support Damian Demasi by becoming a sponsor. Any amount is appreciated!

See recent sponsors |ย Learn more about Hashnode Sponsors
ย 
Share this