React 19 useTransition() hook
In React 18
When a user wants to change their name, the process typically involves typing the new name into an input box and then clicking the submit button (which triggers an API call). After submitting, we receive a response. In this case, we need to manage the following manually using useState() hooks:
Pending states
Errors
Optimistic updates
Sequential requests
Let’s take a look at how this can be done in the example below.
import React, { useState } from 'react';
// Assuming the API call function looks like this
const updateNameApiCall = async (name) => {
try {
const response = await fetch('/update-name', {
method: 'POST',
body: JSON.stringify({ name }),
headers: {
'Content-Type': 'application/json',
},
});
const data = await response.json();
if (!response.ok) {
throw new Error(data.error || 'An error occurred');
}
return null;
} catch (error) {
return error.message;
}
};
export const UpdateName = () => {
const [name, setName] = useState('');
const [error, setError] = useState(null);
const [isPending, setIsPending] = useState(false);
const handleSubmit = async () => {
setIsPending(true);
setError(null);
const error = await updateNameApiCall(name);
setIsPending(false);
if (error) {
setError(error);
}
window.location.href = '/path'; // Redirect after successful submission
};
return (
<div>
<input
value={name}
onChange={(event) => setName(event.target.value)}
disabled={isPending}
/>
<button onClick={handleSubmit} disabled={isPending || !name}>
Update
</button>
{error && <p>{error}</p>}
</div>
);
};
In React 19,
A React team member introduced a hook to manage pending states, errors, forms, and optimistic updates automatically.
The hook is named
useTransition()
.
useTransition()
This hook accepts an asynchronous function as an argument and returns two values:
A pending state
A
startTransition
function.import React, { useState, useTransition } from 'react'; // Simulating the API call function const updateName = async (name) => { try { // Simulate an API call (replace with your actual API call) const response = await fetch('/update-name', { method: 'POST', body: JSON.stringify({ name }), headers: { 'Content-Type': 'application/json', }, }); const data = await response.json(); if (!response.ok) { throw new Error(data.error || 'An error occurred'); } return null; // No error means success } catch (error) { return error.message; } }; export function NewUpdateName() { const [name, setName] = useState(''); const [error, setError] = useState(null); const [isPending, startTransition] = useTransition(); const handleSubmit = () => { startTransition(async () => { const error = await updateName(name); if (error) { setError(error); // Set error if any return; } // On success, redirect the user window.location.href = '/path'; // This will redirect to the desired path }); }; return ( <div> <input value={name} onChange={(event) => setName(event.target.value)} disabled={isPending} // Disable the input while waiting for the transition /> <button onClick={handleSubmit} disabled={isPending || !name}> Update </button> {error && <p>{error}</p>} </div> ); }