JAVASCRIPT
Perform Asynchronous Data Fetching with `useEffect` and `useState`
Master the fundamental React pattern for fetching asynchronous data using `useEffect` and `useState` hooks, including handling loading states and errors.
import { useState, useEffect } from 'react';
function useFetch(url) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
const fetchData = async () => {
setLoading(true);
setError(null); // Clear previous errors
try {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const result = await response.json();
setData(result);
} catch (err) {
setError(err);
} finally {
setLoading(false);
}
};
fetchData();
// Optional: Cleanup function for aborting fetch if component unmounts
// const abortController = new AbortController();
// const signal = abortController.signal;
// fetch(url, { signal }).then(...)
// return () => abortController.abort();
}, [url]); // Re-run effect if URL changes
return { data, loading, error };
}
// Example Usage:
// function UserProfile({ userId }) {
// const { data: user, loading, error } = useFetch(
// `https://jsonplaceholder.typicode.com/users/${userId}`
// );
// if (loading) return <p>Loading user data...</p>;
// if (error) return <p>Error: {error.message}</p>;
// if (!user) return <p>No user found.</p>;
// return (
// <div>
// <h2>{user.name}</h2>
// <p>Email: {user.email}</p>
// <p>Phone: {user.phone}</p>
// </div>
// );
// }
How it works: This `useFetch` custom hook encapsulates the logic for fetching data from a given URL. It uses `useState` to manage the `data`, `loading`, and `error` states. The `useEffect` hook triggers the data fetching when the component mounts or the `url` changes. It handles success, loading indicators, and error conditions, providing a clean interface for consuming asynchronous data in React components. The optional cleanup illustrates how to abort ongoing fetches on unmount.