Appearance
Kapitel 12: Netzwerk-Anfragen
In diesem Kapitel lernen wir, wie man API-Aufrufe in React macht.
12.1 axios Installation und Grundlagen
📦 Installation
bash
# npm
npm install axios
# pnpm (empfohlen)
pnpm add axios📝 Einfache GET-Anfrage
jsx
import axios from 'axios';
import { useState, useEffect } from 'react';
function App() {
const [data, setData] = useState(null);
const [error, setError] = useState(null);
useEffect(() => {
axios.get('https://api.example.com/users')
.then(response => {
setData(response.data);
})
.catch(err => {
setError(err.message);
});
}, []);
if (error) return <p>Fehler: {error}</p>;
if (!data) return <p>Lädt...</p>;
return (
<ul>
{data.map(user => (
<li key={user.id}>{user.name}</li>
))}
</ul>
);
}📝 POST-Anfrage
jsx
import axios from 'axios';
function App() {
const [name, setName] = useState('');
const handleSubmit = () => {
axios.post('https://api.example.com/users', { name })
.then(response => {
console.log('Erfolg:', response.data);
})
.catch(error => {
console.error('Fehler:', error);
});
};
return (
<div>
<input
type="text"
value={name}
onChange={(e) => setName(e.target.value)}
/>
<button onClick={handleSubmit}>Senden</button>
</div>
);
}12.2 Anfragen kapseln (Request Wrapper)
🔧 Axios-Instanz erstellen
axiosInstance.js:
javascript
import axios from 'axios';
const instance = axios.create({
baseURL: 'https://api.example.com',
timeout: 10000, // 10 Sekunden
headers: {
'Content-Type': 'application/json'
}
});
export default instance;🔒 Request Interceptor (Token hinzufügen)
javascript
// axiosInstance.js (fortsetzung)
instance.interceptors.request.use(
config => {
const token = localStorage.getItem('token');
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
},
error => {
return Promise.reject(error);
}
);🛡️ Response Interceptor (Fehlerbehandlung)
javascript
// axiosInstance.js (fortsetzung)
instance.interceptors.response.use(
response => response,
error => {
if (error.response.status === 401) {
// Token abgelaufen → Zur Login-Seite weiterleiten
window.location.href = '/login';
}
return Promise.reject(error);
}
);
export default instance;📦 API-Modul erstellen
api/userApi.js:
javascript
import axiosInstance from './axiosInstance';
export const userApi = {
getUsers: () => axiosInstance.get('/users'),
getUserById: (id) => axiosInstance.get(`/users/${id}`),
createUser: (data) => axiosInstance.post('/users', data),
updateUser: (id, data) => axiosInstance.put(`/users/${id}`, data),
deleteUser: (id) => axiosInstance.delete(`/users/${id}`)
};Verwendung:
jsx
import { userApi } from './api/userApi';
function App() {
const [users, setUsers] = useState([]);
useEffect(() => {
userApi.getUsers()
.then(response => setUsers(response.data))
.catch(error => console.error(error));
}, []);
return (
<ul>
{users.map(user => (
<li key={user.id}>{user.name}</li>
))}
</ul>
);
}12.3 useEffect mit axios kombinieren
⚠️ Problem: Doppelte Anfragen
jsx
// ❌ Falsch: Kein Abhängigkeitsarray
useEffect(() => {
axios.get('/api/data');
}); // Wird bei jedem Rendering ausgeführt!
// ✅ Richtig: Leeres Array (nur einmal)
useEffect(() => {
axios.get('/api/data');
}, []);
// ✅ Richtig: Mit Abhängigkeiten (bei Änderung)
const [userId, setUserId] = useState(1);
useEffect(() => {
axios.get(`/api/users/${userId}`);
}, [userId]);🧹 Aufräumen (Cleanup)
jsx
useEffect(() => {
const source = axios.CancelToken.source();
axios.get('/api/data', {
cancelToken: source.token
});
return () => {
source.cancel('Componente wurde unmounted');
};
}, []);12.4 CORS-Probleme lösen
🤔 Was ist CORS?
CORS (Cross-Origin Resource Sharing): Browser blockiert Anfragen an eine andere Domain.
Beispiel:
Frontend: http://localhost:3000
Backend: http://api.example.com
→ CORS-Fehler!🔧 Lösung 1: Proxy (Entwicklung)
Vite (vite.config.js):
javascript
export default {
server: {
proxy: {
'/api': {
target: 'http://api.example.com',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, '')
}
}
}
};Create React App (package.json):
json
{
"proxy": "http://api.example.com"
}🔧 Lösung 2: Backend-Anpassung
Node.js (Express):
javascript
const express = require('express');
const app = express();
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', 'http://localhost:3000');
res.header('Access-Control-Allow-Headers', 'Authorization, Content-Type');
res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
next();
});
app.listen(3000);12.5 Lade- und Fehlerzustände
🔄 Loading & Error State
jsx
function App() {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
axios.get('https://api.example.com/users')
.then(response => {
setData(response.data);
setLoading(false);
})
.catch(err => {
setError(err.message);
setLoading(false);
});
}, []);
if (loading) return <p>Lädt...</p>;
if (error) return <p>Fehler: {error}</p>;
return (
<ul>
{data.map(user => (
<li key={user.id}>{user.name}</li>
))}
</ul>
);
}🎨 Benutzerfreundlichkeit verbessern
jsx
function App() {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
const fetchData = () => {
setLoading(true);
setError(null);
axios.get('https://api.example.com/users')
.then(response => {
setData(response.data);
setLoading(false);
})
.catch(err => {
setError(err.message);
setLoading(false);
});
};
return (
<div>
<button onClick={fetchData} disabled={loading}>
{loading ? 'Lädt...' : 'Daten abrufen'}
</button>
{error && <p style={{ color: 'red' }}>Fehler: {error}</p>}
{data && (
<ul>
{data.map(user => (
<li key={user.id}>{user.name}</li>
))}
</ul>
)}
</div>
);
}12.6 Alternative: fetch API
📝 fetch Grundlagen
jsx
useEffect(() => {
fetch('https://api.example.com/users')
.then(response => response.json())
.then(data => setData(data))
.catch(error => setError(error.message));
}, []);🔄 fetch mit async/await
jsx
const fetchData = async () => {
try {
const response = await fetch('https://api.example.com/users');
const data = await response.json();
setData(data);
} catch (error) {
setError(error.message);
}
};
useEffect(() => {
fetchData();
}, []);🔄 axios vs. fetch
| Merkmal | axios | fetch |
|---|---|---|
| Installation | Erforderlich | Eingebaut |
| JSON automatisch | ✅ Ja | ❌ Nein (.json()) |
| Request/Response Interceptors | ✅ Ja | ❌ Nein |
| Abbrechen von Anfragen | ✅ Einfach | ⚠️ Komplex |
| Timeout | ✅ Einfach | ❌ Komplex |
Empfehlung: Verwenden Sie axios (einfacher und mächtiger).
📝 Zusammenfassung
In diesem Kapitel haben wir gelernt:
- ✅ axios Installation und Grundlagen
- ✅ Anfragen kapseln (Request Wrapper)
- ✅ Interceptors (Request & Response)
- ✅ useEffect mit axios kombinieren
- ✅ CORS-Probleme lösen (Proxy, Backend)
- ✅ Lade- und Fehlerzustände verwalten
- ✅ fetch API als Alternative
🎯 Nächste Schritte
Im nächsten Kapitel werden wir lernen:
- Fortgeschrittene Konzepte (Performance-Optimierung)
- memo, useMemo, useCallback
- Error Boundaries und Lazy Loading
Bereit für fortgeschrittene Themen? → Kapitel 13: Fortgeschrittene Konzepte
