How to make API requests in React using the Fetch API.
Fetching data from an API using useEffect.
import { useState, useEffect } from 'react';
function UserList() {
const [users, setUsers] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
// Fetch users when component mounts
fetch('https://api.example.com/users')
.then(response => {
if (!response.ok) {
throw new Error('Network response was not ok');
}
return response.json();
})
.then(data => {
setUsers(data);
setLoading(false);
})
.catch(error => {
setError(error.message);
setLoading(false);
});
}, []);
if (loading) return <div>Loading...</div>;
if (error) return <div>Error: {error}</div>;
return (
<ul>
{users.map(user => (
<li key={user.id}>{user.name}</li>
))}
</ul>
);
}Sending data to an API using fetch.
import { useState } from 'react';
function CreateUser() {
const [name, setName] = useState('');
const [email, setEmail] = useState('');
const [status, setStatus] = useState(null);
const handleSubmit = async (e) => {
e.preventDefault();
setStatus('loading');
try {
const response = await fetch('https://api.example.com/users', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ name, email }),
});
if (!response.ok) {
throw new Error('Failed to create user');
}
const data = await response.json();
setStatus('success');
setName('');
setEmail('');
console.log('User created:', data);
} catch (error) {
setStatus('error');
console.error('Error:', error);
}
};
return (
<form onSubmit={handleSubmit}>
<div>
<label htmlFor="name">Name:</label>
<input
id="name"
type="text"
value={name}
onChange={(e) => setName(e.target.value)}
required
/>
</div>
<div>
<label htmlFor="email">Email:</label>
<input
id="email"
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
required
/>
</div>
<button type="submit" disabled={status === 'loading'}>
{status === 'loading' ? 'Creating...' : 'Create User'}
</button>
{status === 'success' && <p>User created successfully!</p>}
{status === 'error' && <p>Failed to create user.</p>}
</form>
);
}Creating a reusable hook for data fetching.
import { useState, useEffect } from 'react';
// Custom hook for data fetching
function useFetch(url) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
// Reset state when URL changes
setLoading(true);
setData(null);
setError(null);
const fetchData = async () => {
try {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
const result = await response.json();
setData(result);
setLoading(false);
} catch (error) {
setError(error.message);
setLoading(false);
}
};
fetchData();
}, [url]);
return { data, loading, error };
}
// Using the custom hook
function UserProfile({ userId }) {
const { data, loading, error } = useFetch(
`https://api.example.com/users/${userId}`
);
if (loading) return <div>Loading...</div>;
if (error) return <div>Error: {error}</div>;
if (!data) return null;
return (
<div>
<h1>{data.name}</h1>
<p>Email: {data.email}</p>
</div>
);
}Making authenticated API requests.
import { useState, useEffect } from 'react';
function ProtectedResource() {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
// Assume we have a token stored in localStorage
const token = localStorage.getItem('authToken');
useEffect(() => {
if (!token) {
setError('No authentication token found');
setLoading(false);
return;
}
const fetchProtectedData = async () => {
try {
const response = await fetch('https://api.example.com/protected-resource', {
headers: {
'Authorization': `Bearer ${token}`,
},
});
if (response.status === 401) {
// Token expired or invalid
localStorage.removeItem('authToken');
setError('Authentication expired. Please log in again.');
setLoading(false);
return;
}
if (!response.ok) {
throw new Error('Failed to fetch data');
}
const result = await response.json();
setData(result);
setLoading(false);
} catch (error) {
setError(error.message);
setLoading(false);
}
};
fetchProtectedData();
}, [token]);
if (loading) return <div>Loading...</div>;
if (error) return <div>Error: {error}</div>;
if (!data) return null;
return (
<div>
<h1>Protected Data</h1>
<pre>{JSON.stringify(data, null, 2)}</pre>
</div>
);
}