React’s use
API introduces a more flexible way to handle asynchronous data and context in React applications. This new addition to React's toolkit simplifies how developers work with Promises and context, offering advantages over traditional methods.
What is the use
API?
The use
API is a React function that lets you read values from resources like Promises or context. Unlike traditional React hooks, use
can be called conditionally and within loops.
import { use } from 'react';
function MessageComponent({ messagePromise }) {
const message = use(messagePromise);
// Now you can work with the resolved value
}
Comparing Data Fetching Approaches
Traditional Approach with useEffect
Previously, the standard way to fetch data in React involved useEffect
and state management:
function OldMessageComponent() {
const [message, setMessage] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
async function fetchData() {
try {
setLoading(true);
const response = await fetch('/api/message');
const data = await response.json();
setMessage(data);
} catch (err) {
setError(err);
} finally {
setLoading(false);
}
}
fetchData();
}, []);
if (loading) return <p>Loading...</p>;
if (error) return <p>Error loading message</p>;
return <p>Message: {message}</p>;
}
Modern Approach with use
With the use
API, the code becomes more concise and integrates with Suspense:
function NewMessageComponent({ messagePromise }) {
const message = use(messagePromise);
return <p>Message: {message}</p>;
}
function ParentComponent() {
const messagePromise = fetchMessage(); // Returns a Promise
return (
<Suspense fallback={<p>Loading...</p>}>
<ErrorBoundary fallback={<p>Error loading message</p>}>
<NewMessageComponent messagePromise={messagePromise} />
</ErrorBoundary>
</Suspense>
);
}
Understanding the Transition: From useEffect
to use
What Happened to Loading States?
In the traditional approach with useEffect
, we manually managed loading states:
const [loading, setLoading] = useState(true);
// Later in the code
setLoading(true);
// After fetch completes
setLoading(false);
// And we conditionally render based on this state
if (loading) return <p>Loading...</p>;
With the use
API, loading states are handled by React's Suspense mechanism:
<Suspense fallback={<p>Loading...</p>}>
<NewMessageComponent messagePromise={messagePromise} />
</Suspense>
The component calling use(messagePromise)
automatically "suspends" while the Promise is pending. During this time, React displays the Suspense fallback UI. Once the Promise resolves, React automatically renders the component with the resolved data. No manual loading state management is needed.
What Happened to Error States?
In the traditional approach, we manually caught and managed errors:
const [error, setError] = useState(null);
// In try/catch block
try {
// fetch code
} catch (err) {
setError(err);
}
// And we conditionally render based on this state
if (error) return <p>Error loading message</p>;
With the use
API, error handling is delegated to React's Error Boundary system:
<ErrorBoundary fallback={<p>Error loading message</p>}>
<NewMessageComponent messagePromise={messagePromise} />
</ErrorBoundary>
If the Promise passed to use
is rejected, React automatically shows the nearest Error Boundary's fallback UI. This eliminates the need for manual error state variables and conditional rendering.
Key Differences
So, what are the key differences between the new and old ways?
Declarative vs Imperative: The new approach is declarative (you describe what should happen) rather than imperative (manually controlling each step).
State Management: Loading and error states are no longer managed with useState hooks but are built into React’s Suspense and Error Boundary features.
Separation of Concerns: UI components simply consume and render the data. Loading and error handling are managed by wrapper components
Flexibility: Unlike hooks like
useContext
,use
can be called within conditional statements and loops.Simplified Code: Reduces boilerplate compared to managing loading and error states manually.
Want to learn how to build faster, cleaner and more maintainable applications with the latest React 19 features? Go here →