Simplifying Async Operations with the New use API in React 19
Simplifying Async Operations with the New use API in React 19
I'll show you how to simplify async operations in React components using the new use API in React 19.
It's always a struggle to find the right pattern to use promises in a component. The most straightforward way is to use the useEffect
hook to call a promise and set the state of the component. I always found that the useEffect hook has the downside of managing the dependency array, which is a bit of a pain.
But since React 19, the use
API has been introduced to deal with promises and it's a lot easier to implement and I find it more maintainable. Let's see how the new use API works by comparing it to the useEffect hook with a code example the fetches a todo from a REST API.
Using the useEffect hook
import { useEffect } from 'react';
function someApiClient(id: string) {
return fetch(`https://jsonplaceholder.typicode.com/todos/${id}`).then(res => res.json());
}
function Todo({data}: {data: Record<string, string>}) {
return (<h1>{data.title}</h1>);
}
function App () {
const [data, setData] = useState<Record<string, string>>({});
const [loading, setLoading] = useState<boolean>(true);
useEffect(() => {
someApiClient(1).then(setData).finally(() => setLoading(false));
}, []);
return (<div>{loading ? 'Loading...' : <Todo data={data} />}</div>);
};
Using the new use API in React 19
In the following example we are using the use
API to wait for the promise to resolve and render the resolved value. By wrapping the Todo component with the Suspense
component will the app will show a loading state while the promise is pending.
import { use } from 'react';
function someApiClient(id: string) {
return fetch(`https://jsonplaceholder.typicode.com/todos/${id}`).then(res => res.json());
}
function App() {
return (
<Suspense fallback={<div>Loading...</div>}>
<Todo someApiClient={someApiClient(1)} />
</Suspense>
);
}
function Todo({someApiClient}: {someApiClient: Promise<Record<string, string>>>}) {
const data = use(someApiClient);
return (<h1>{data.title}</h1>);
}
Warning: Do not create the promise directly within the use
function. Doing so will cause a render loop
In my opinion, the new use API is a lot more straightforward and cleaner than the useEffect approach. It's even possible to use it conditionally and that's not possible with hooks like useEffect. I hope this helps you simplify async operations in components and make your code more maintainable. Feel free to contact me at randy@divotion.com if you have any questions or suggestions.
And happy coding!