Explizite Datenabrufe in React
Explizite Datenabrufe in React
Das erneute Abrufen aller Daten bei jeder Eingabe in das Eingabefeld ist nicht optimal. Wir verwenden hierzu eine Drittanbieter-API, deren Interna nicht in unserem Einflussbereich ist. Wenn wir Pech haben, wird uns aufgrund einer Durchsatzratenbegrenzung, anstelle der Daten eine Fehlermeldung zurückgeben.
Um dieses Problem zu lösen, verändern wir die Art des Datenabrufs von implizit zu explizit. Mit anderen Worten, die Anwendung ruft Daten nur dann ab, wenn jemand auf eine Bestätigungsschaltfläche klickt. Fügen wir zunächst ein Schaltflächenelement für die Bestätigung mittels JSX zu unserer Benutzeroberfläche hinzu:
const App = () => {
...
return (
<div>
<h1>My Hacker Stories</h1>
<InputWithLabel
id="search"
value={searchTerm}
isFocused
# start-insert
onInputChange={handleSearchInput}
# end-insert
>
<strong>Search:</strong>
</InputWithLabel>
# start-insert
<button
type="button"
disabled={!searchTerm}
onClick={handleSearchSubmit}
>
Submit
</button>
# end-insert
...
</div>
);
};
Im Anschluss daran implementieren wir bei den Ereignis-Handlern alles Notwendige, um den Status der Komponente zu aktualisieren. Der Eingabefeld-Handler aktualisiert weiterhin den searchTerm
. Der Schaltflächen-Handler setzt die url
, die sich aus dem aktuellen searchTerm
und der hartcodierten statischen API-URL ableitet, als neuen Status:
const App = () => {
const [searchTerm, setSearchTerm] = useSemiPersistentState(
'search',
'React'
);
# start-insert
const [url, setUrl] = React.useState(
`${API_ENDPOINT}${searchTerm}`
);
# end-insert
...
# start-insert
const handleSearchInput = event => {
# end-insert
setSearchTerm(event.target.value);
};
# start-insert
const handleSearchSubmit = () => {
setUrl(`${API_ENDPOINT}${searchTerm}`);
};
# end-insert
...
};
Am Ende wird der Seiten-Effekt des Datenabrufs nicht mehr bei jeder Änderung von searchTerm
aufgerufen. Anstelle davon verwenden wir die url
um die Liste zu aktualisieren. Diese wird vom Benutzer festgelegt, wenn er die Suche über die neue Schaltfläche bestätigt:
const App = () => {
...
const handleFetchStories = React.useCallback(() => {
dispatchStories({ type: 'STORIES_FETCH_INIT' });
# start-insert
fetch(url)
# end-insert
.then(response => response.json())
.then(result => {
dispatchStories({
type: 'STORIES_FETCH_SUCCESS',
payload: result.hits,
});
})
.catch(() =>
dispatchStories({ type: 'STORIES_FETCH_FAILURE' })
);
# start-insert
}, [url]);
# end-insert
React.useEffect(() => {
handleFetchStories();
}, [handleFetchStories]);
...
};
searchTerm
hatte bisher zwei Aufgaben: Zum einen war die Variable für die Aktualisierung des Status des Eingabefelds zuständig. Zum andere war sie für den Abruf der Daten verantwortlich --- sie löste den Seiten-Effekt aus. Dies war kein idealer Programmierstil, weil die Zuständigkeiten nicht getrennt waren. Jetzt wird searchTerm
nur für die Aktualisierung des Eingabefelds verwendet. Eine zweite Variable namens url
wurde eingeführt, um den Seiten-Effekt beim Abrufen von Daten auszulösen. Dieser tritt nur dann auf, wenn ein Benutzer auf die Bestätigungsschaltfläche klickt.
Übungen:
- Begutachte den Quellcode dieses Abschnitts.
- Reflektiere die Änderungen gegenüber dem letzten Abschnitt.
- Warum wird
useState
anstelle vonuseSemiPersistentState
für dieurl
-Statusverwaltung verwendet? - Die Suche nach einem leeren
searchTerm
wird nicht mehr explizit verhindert. Warum haben wirif (!searchTerm) return;
in der FunktionhandleFetchStories
entfernt?