How to use Transitions in React 18
Tags: react, javascript, webdev, programming
Published: 2022-04-25 15:29:40

---
title: How to use Transitions in React 18
published: true
date: 2022-04-25 09:13:48 UTC
tags: React, javascript, webdev, programming
canonical_url: https://blog.shahednasser.com/how-to-use-transitions-in-react-18/
cover_image: https://blog.shahednasser.com/static/a653d678a3e8e1cde9337a2091d4db0c/How-to-use-Transitions-in-React-18-2.jpg
---

_Originally posted on [my personal blog](https://blog.shahednasser.com/how-to-use-transitions-in-react-18/)._

[React 18 came out at the end of March](https://reactjs.org/blog/2022/03/29/react-v18.html) with a bundle of new features. One of these new features is Transitions.

In this tutorial, you'll learn more about Transitions in React 18 and see them in action.

## Definition

You have 2 types of transitions. Urgent transitions and non-urgent transitions.

### Urgent Transitions

Urgent transitions are transitions that the user needs to see instantly. For example, if the user changes their profile name and saves it, they should be able to see the change in the displayed profile name in the navigation bar.

Urgent transitions are done the same way you've been setting a state before:

```
const [name, setName] = useState('');

function handleChange (e) {
	setName(e.target.value); //urgent transition
}
```

### Non-Urgent Transitions

Non-urgent transitions are transitions that are ok to be delayed a little. For example, if the user is performing a search, it's ok for the results to appear not so instantly.

There are 2 ways to start a non-urgent transition. The first one is using the hook `useTransition`:

```
import {useTransition, useState} from 'react';

export default function MyApp() {
    const [results, setResults] = useState([]);
    const [pending, startTransition] = useTransition();
    
    function handleChange(e) {
        let tempResults = [];
        ... // set results from APIs
        startTransition(() => {
            setResults(tempResults);
        });
    }
}
```

The hook returns the boolean variable `pending` which indicates whether the transition is active or not. It can be used to show a loading component.

The hook also returns a function `startTransition` that accepts a callback function in which you set the state. The state will not be set immediately.

The second way to start a non-urgent transition is using the function `startTransition` imported directly from React:

```
import {startTransition} from 'react';

export default function MyApp() {
    const [results, setResults] = useState([]);
    
    function handleChange(e) {
        let tempResults = [];
        ... // set results from APIs
        startTransition(() => {
            setResults(tempResults);
        });
    }
}
```

This approach does not give you access to a variable like `isPending` to check whether the transition is active or not.

This approach is mainly available for places in your code when you can't use hooks like `useTransition`.

## Usage Example

In this example, you'll be creating a number input that accepts a large number of images to be shown. Then, random images will be retrieved using [Falso](https://ngneat.github.io/falso/).

Start by creating a new React app if you don't have one available:

```
npx create-react-app my-app
```

Next, change into the directory `my-app`:

```
cd my-app
```

Then, install the Falso library:

```
npm i @ngneat/falso
```

Now, open `src/App.js` and change it to the following:

```
import './App.css';

import { useState, useTransition } from 'react';

import { randImg } from '@ngneat/falso';

function App() {
  const [number, setNumber] = useState(5000);
  const [images, setImages] = useState([])
  const [isPending, startTransition] = useTransition();

  function showImages() {
    //TODO add transition
  }

  return (
    <div style={{
      padding: '10px'
    }}>
      <h1>Images</h1>
      <div>
        <label>Number of images</label>
        <input type="number" min="1" max="10000" value={number} onChange={(e) => setNumber(e.target.value)} style={{
          display: 'block',
          marginTop: '10px',
          width: '3rem'
        }} />
        <button type="button" onClick={showImages} style={{marginTop: '10px'}}>Show Images</button>
      </div>
      <div>
        <span>Number selected: {number}</span><br/>
        <span>Results:</span>
        {isPending && <span>Loading...</span>}
        {!isPending && images.length > 0 && images}
      </div>
    </div>
  );
}

export default App;

```

You first create 2 state variables `number` and `images`. You also use `useTransition` which gives you access to `isPending` and `startTransition`.

In the returned JSX, you show a number input and a button that will later retrieve the images on click.

Below the input and button, the number entered by the user in the input will be shown. Notice that in the `onChange` event handler for the input the name is updated **urgently.** This will show the number instantly as it is updated by the user.

Let's test it out now. Run the website server:

```
npm start
```

This will open the website in your browser. If you try to update the input, you'll notice that the number displayed below it will update instantly.

<video src="https://backend.shahednasser.com/content/media/2022/04/Screen-Recording-2022-04-23-at-3.45.38-PM.mp4" poster="https://img.spacergif.org/v1/798x692/0a/spacer.png" width="798" height="692" playsinline="" preload="metadata" style="background: transparent url('https://backend.shahednasser.com/content/images/2022/04/media-thumbnail-ember409.jpg') 50% 50% / cover no-repeat;"></video>
<button><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24"><path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"></path></svg></button>

<button><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24"><path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"></path></svg></button><button><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24"><rect x="3" y="1" width="7" height="22" rx="1.5" ry="1.5"></rect><rect x="14" y="1" width="7" height="22" rx="1.5" ry="1.5"></rect></svg></button>0:00
/
<input type="range" max="100" value="0"><button>1×</button><button><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24"><path d="M15.189 2.021a9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h1.794a.249.249 0 0 1 .221.133 9.73 9.73 0 0 0 7.924 4.85h.06a1 1 0 0 0 1-1V3.02a1 1 0 0 0-1.06-.998Z"></path></svg></button><button><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24"><path d="M16.177 4.3a.248.248 0 0 0 .073-.176v-1.1a1 1 0 0 0-1.061-1 9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h.114a.251.251 0 0 0 .177-.073ZM23.707 1.706A1 1 0 0 0 22.293.292l-22 22a1 1 0 0 0 0 1.414l.009.009a1 1 0 0 0 1.405-.009l6.63-6.631A.251.251 0 0 1 8.515 17a.245.245 0 0 1 .177.075 10.081 10.081 0 0 0 6.5 2.92 1 1 0 0 0 1.061-1V9.266a.247.247 0 0 1 .073-.176Z"></path></svg></button><input type="range" max="100" value="100">

Now, let's test the non-urgent transition. In `showImages` replace the `TODO` with the following code:

```
const imgSources = randImg({length: number}).map((url, index) => <img src={`${url}?v=${index}`} key={index} />);
startTransition(() => {
	setImages(imgSources);
})
```

This will get the images using the `falso` library and inside `startTransition` with set the `images` state variable.

Notice that in the returned JSX of the function we use `isPending` to indicate whether to show "Loading..." or not.

If you try clicking on the button now, the "Loading..." text will show first, and then the images will be shown gradually.

<video src="https://backend.shahednasser.com/content/media/2022/04/Screen-Recording-2022-04-23-at-4.01.34-PM.mp4" poster="https://img.spacergif.org/v1/794x896/0a/spacer.png" width="794" height="896" playsinline="" preload="metadata" style="background: transparent url('https://backend.shahednasser.com/content/images/2022/04/media-thumbnail-ember441.jpg') 50% 50% / cover no-repeat;"></video>
<button><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24"><path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"></path></svg></button>

<button><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24"><path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"></path></svg></button><button><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24"><rect x="3" y="1" width="7" height="22" rx="1.5" ry="1.5"></rect><rect x="14" y="1" width="7" height="22" rx="1.5" ry="1.5"></rect></svg></button>0:00
/
<input type="range" max="100" value="0"><button>1×</button><button><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24"><path d="M15.189 2.021a9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h1.794a.249.249 0 0 1 .221.133 9.73 9.73 0 0 0 7.924 4.85h.06a1 1 0 0 0 1-1V3.02a1 1 0 0 0-1.06-.998Z"></path></svg></button><button><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24"><path d="M16.177 4.3a.248.248 0 0 0 .073-.176v-1.1a1 1 0 0 0-1.061-1 9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h.114a.251.251 0 0 0 .177-.073ZM23.707 1.706A1 1 0 0 0 22.293.292l-22 22a1 1 0 0 0 0 1.414l.009.009a1 1 0 0 0 1.405-.009l6.63-6.631A.251.251 0 0 1 8.515 17a.245.245 0 0 1 .177.075 10.081 10.081 0 0 0 6.5 2.92 1 1 0 0 0 1.061-1V9.266a.247.247 0 0 1 .073-.176Z"></path></svg></button><input type="range" max="100" value="100">

## Conclusion

Transitions in React 18 allow you to optimize your user experience, especially for tasks or features that require some time to load. You can now use Transitions in React 18 to differentiate between instate updates and updates that can be delayed, and show in the UI any necessary loading more efficiently for those that require more time.