How to use Transitions in React 18
Shahed Nasser
Posted on April 25, 2022
Originally posted on my personal blog.
React 18 came out at the end of March 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.
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.
0:00
/
1×
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.
0:00
/
1×
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.
Posted on April 25, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
October 16, 2024