5 use cases of the useState ReactJS hook
Tags: react, javascript, webdev, hooks
Published: 2021-09-16 22:30:59

`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:

```jsx
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:

```jsx
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.

```jsx
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:

```jsx
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:

```jsx
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.

```jsx
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](https://6142b64c2e448f0007271a3f--romantic-booth-593b0c.netlify.app/).

You can also take a look at the code in [this repository](https://github.com/Colo-Codes/react-hooks-use-cases/tree/main/src/components/UseCaseUseState).