Eine React App läuft in dem Browser des Besuchers. Um Daten zwischen den Besuchern austauschen zu können wird eine Datenbank benötigt. Aus Sicherheitsgründen soll vermieden werden eine Verbindung direkt zur Datenbank herzustellen, da diese im Browser gesehen werden kann. In der Regel wird die Kommunikation mit einer Datenbank über ein Backend gelöst.
Beispiel Daten aus dem Backend mithilfe HTTP Request holen
useEffect(() => {
fetch('http://localhost:3000/places').then((response) => {
return response.json()
}).then((resData) => {
setAvailablePlaces(resData.places);
});
}, []);
useEffect(() => {
async function fetchPlaces() {
const response = await fetch('http://localhost:3000/places');
const resData = await response.json();
setAvailablePlaces(resData.places);
}
fetchPlaces();
}, []);
Wird geladen Meldung
//AvailablePlaces.jsx
import { useEffect, useState } from 'react';
import Places from './Places.jsx';
export default function AvailablePlaces({ onSelectPlace }) {
const [isFetching, setIsFetching] = useState(false);
const [availablePlaces, setAvailablePlaces] = useState([]);
useEffect(() => {
async function fetchPlaces() {
setIsFetching(true);
const response = await fetch('http://localhost:3000/places');
const resData = await response.json();
setAvailablePlaces(resData.places);
setIsFetching(false);
}
fetchPlaces();
}, []);
return (
<Places
title="Available Places"
places={availablePlaces}
isLoading={isFetching}
loadingText="Fetching place data..."
fallbackText="No places available."
onSelectPlace={onSelectPlace}
/>
);
}
//Places.jsx
export default function Places({ title, places, fallbackText, onSelectPlace, isLoading, loadingText
}) {
console.log(places);
return (
<section className="places-category">
<h2>{title}</h2>
{isLoading && <p className="fallback-text">{loadingText}</p>}
{!isLoading && places.length === 0 && <p className="fallback-text">{fallbackText}</p>}
{!isLoading && places.length > 0 && (
<ul className="places">
{places.map((place) => (
<li key={place.id} className="place-item">
<button onClick={() => onSelectPlace(place)}>
<img src={`http://localhost:3000/${place.image.src}`} alt={place.image.alt} />
<h3>{place.title}</h3>
</button>
</li>
))}
</ul>
)}
</section>
);
}
Umgang mit Fehler bei Senden/Empfangen von Daten per HTTP
//AvailablePlaces.jsx
import { useEffect, useState } from 'react';
import Places from './Places.jsx';
import Error from './Error.jsx';
export default function AvailablePlaces({ onSelectPlace }) {
const [isFetching, setIsFetching] = useState(false);
const [availablePlaces, setAvailablePlaces] = useState([]);
const [error, setError] = useState();
useEffect(() => {
async function fetchPlaces() {
setIsFetching(true);
try {
const response = await fetch('http://localhost:3000/places1');
const resData = await response.json();
// 200, 300 => ok
// 400, 500 => not ok
if (!response.ok) {
throw new Error('Failed to fetch places');
}
setAvailablePlaces(resData.places);
} catch (error) {
setError({message: error.message || 'Could not fetch places, please try again later'});
}
setIsFetching(false);
}
fetchPlaces();
}, []);
if (error) {
return <Error title="An error occurred!" message={error.message}/>
}
return (
<Places
title="Available Places"
places={availablePlaces}
isLoading={isFetching}
loadingText="Fetching place data..."
fallbackText="No places available."
onSelectPlace={onSelectPlace}
/>
);
}
//Error.jsx
export default function Error({ title, message, onConfirm }) {
return (
<div className="error">
<h2>{title}</h2>
<p>{message}</p>
{onConfirm && (
<div id="confirmation-actions">
<button onClick={onConfirm} className="button">
Okay
</button>
</div>
)}
</div>
);
}