Wat is Data Fetching?
Data fetching is het ophalen van data van een server/API. In React gebruik je de fetch() functie binnen een useEffect hook.
Typisch patroon:
- Component mount → useEffect
- Fetch data van API
- Zet data in state
- Component rendert opnieuw met data
Basis Fetch met .then()
import { useState, useEffect } from 'react';
const Users = () => {
const [users, setUsers] = useState([]);
useEffect(() => {
fetch('https://jsonplaceholder.typicode.com/users')
.then(response => response.json())
.then(data => setUsers(data));
}, []); // Lege array = 1x uitvoeren
return (
<ul>
{users.map(user => (
<li key={user.id}>{user.name}</li>
))}
</ul>
);
};
export default Users;
Stappen:
fetch(url)- Haal data op.then(res => res.json())- Converteer naar JSON.then(data => setUsers(data))- Zet in state
Fetch met async/await (beter!)
Async/await is moderner en leesbaarder dan .then():
import { useState, useEffect } from 'react';
const Users = () => {
const [users, setUsers] = useState([]);
useEffect(() => {
const fetchUsers = async () => {
const response = await fetch('https://jsonplaceholder.typicode.com/users');
const data = await response.json();
setUsers(data);
};
fetchUsers();
}, []);
return (
<ul>
{users.map(user => (
<li key={user.id}>{user.name}</li>
))}
</ul>
);
};
Let op: Je kunt useEffect zelf niet async maken! Maak een aparte async functie binnen useEffect.
Met Loading en Error Handling
import { useState, useEffect } from 'react';
const Users = () => {
const [users, setUsers] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState('');
useEffect(() => {
const fetchUsers = async () => {
try {
setLoading(true);
const response = await fetch('https://jsonplaceholder.typicode.com/users');
if (!response.ok) {
throw new Error('Er ging iets mis');
}
const data = await response.json();
setUsers(data);
} catch (err) {
setError(err.message);
} finally {
setLoading(false);
}
};
fetchUsers();
}, []);
if (loading) return <p>Loading...</p>;
if (error) return <p>Error: {error}</p>;
return (
<ul>
{users.map(user => (
<li key={user.id}>{user.name}</li>
))}
</ul>
);
};
POST Request (data versturen)
Om data naar een API te versturen gebruik je een POST request:
const CreateUser = () => {
const [name, setName] = useState('');
const [loading, setLoading] = useState(false);
const handleSubmit = async (e) => {
e.preventDefault();
setLoading(true);
try {
const response = await fetch('https://jsonplaceholder.typicode.com/users', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ name })
});
const data = await response.json();
console.log('User created:', data);
setName(''); // Reset form
} catch (error) {
console.error('Error:', error);
} finally {
setLoading(false);
}
};
return (
<form onSubmit={handleSubmit}>
<input
value={name}
onChange={(e) => setName(e.target.value)}
placeholder="Naam"
/>
<button type="submit" disabled={loading}>
{loading ? 'Bezig...' : 'Maak User'}
</button>
</form>
);
};
POST request opties:
method: 'POST'- Type requestheaders- Metadata (bijv. Content-Type)body- Data als JSON string
Praktische Voorbeelden
Single Item Fetchen
const UserDetail = ({ userId }) => {
const [user, setUser] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
const fetchUser = async () => {
const response = await fetch(`https://jsonplaceholder.typicode.com/users/${userId}`);
const data = await response.json();
setUser(data);
setLoading(false);
};
fetchUser();
}, [userId]); // Re-fetch als userId verandert
if (loading) return <p>Loading...</p>;
if (!user) return <p>User not found</p>;
return (
<div>
<h2>{user.name}</h2>
<p>{user.email}</p>
</div>
);
};
Update (PUT/PATCH)
const updateUser = async (userId, newData) => {
const response = await fetch(`https://jsonplaceholder.typicode.com/users/${userId}`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(newData)
});
const data = await response.json();
return data;
};
Delete
const deleteUser = async (userId) => {
const response = await fetch(`https://jsonplaceholder.typicode.com/users/${userId}`, {
method: 'DELETE'
});
if (response.ok) {
console.log('User deleted');
}
};
Refetch Button
const Users = () => {
const [users, setUsers] = useState([]);
const [loading, setLoading] = useState(false);
const fetchUsers = async () => {
setLoading(true);
const response = await fetch('https://jsonplaceholder.typicode.com/users');
const data = await response.json();
setUsers(data);
setLoading(false);
};
useEffect(() => {
fetchUsers();
}, []);
return (
<div>
<button onClick={fetchUsers} disabled={loading}>
{loading ? 'Loading...' : 'Refresh'}
</button>
<ul>
{users.map(user => (
<li key={user.id}>{user.name}</li>
))}
</ul>
</div>
);
};