Custom hook z użyciem useState() i useEffect()
Aby pobierać dane z jakiegokolwiek API za pomocą wbudowanych hooków Reacta, można wprowadzić custom hook - useFetch, który wewnętrznie wykorzystuje useState i useEffect
import { useState, useEffect } from 'react'
const useFetch = url => {
const [state, setState] = useState([null, false]);
useEffect(() => {
setState([null, true]);
(async () => {
const data = await fetch(url)
.then(res => res.json());
setState([data.body, false]);
})();
}, [url]);
return state;
};
export default useFetch;
Ta funkcja zwraca tablicę z dwiema zmiennymi: zawartością stanu i flagą ładowania.
Domyślnie, w linii:4, widać, że zaczynamy od wartości null i false. Nic się nie ładuje.
Ale potem ustawiamy ładowanie na true w linii:8 i wewnątrz anonimowej funkcji asynchronicznej pobieramy dane.
Gdy dane zostaną zwrócone, aktualizujemy stan za pomocą funckji setState, do której jako pierszy element w tablicy przekazujemy wartość stanu i drugi element ustawiamy na false ponieważ pobieranie danych z API zostało zakończone.
Należy pamiętać, że nie można bezpośrednio wywołać asynchronicznego callbacka w useEffect. Dlatego należy zdefiniować w nim oddzielną funkcję asynchroniczną.
Skorzystałem tutaj z IIFE, czyli Immediately-invoked function expression. Jak sama nazwa mówi jest to natychmiastowo samowywołująca się funkcja. Czyli funkcja, która wykonuje się od razu.
Robimy tak gdy chcemy natychmiast wywołać funkcję i nie ma potrzeby jej definiowania a następnie wywoływania.
Możesz przekazać adres url do tablicy zależności useEffect. Dla Reacta oznacza to, aby ponownie wywołał hook useEffect() tylko wtedy, gdy zmieni się adres URL.
Aby użyć tego hooka, możesz wprowadzić go do swojego komponentu w następujący sposób:
// Po zaimportowaniu hooka useFetch
const Post = () => {
const [post, loading] = useFetch('https://jsonplaceholder.typicode.com/posts/1');
if (loading) {
return <Loading />
}
return <PostBody content={post} />;
};
Jak radzić sobie z obsługą błędów w przypadku pobierania danych z API?
Tradycyjnym sposobem uzyskania danych lub informacji o błędzie z Promisa jest użycie then i catch.
import React, { useState, useEffect } from 'react'
function FetchAPI() {
const [users, setUsers] = useState([])
const [isError, setIsError] = useState(false);
useEffect(() => {
fetch('https://jsonplaceholder.typicode.com/users').then((response) => {
if (response.ok) {
return response.json();
} else {
throw 'Error getting users list'
}
}).then((data) => {
setUsers(data);
}).catch((error) => {
setIsError(true)
})
}, [])
return (
<div>
{isError ? <h3> Error! Please try again later</h3> :
<ul>
{users.map((user) => <li key={user.id} > {user.name} </li>)}
</ul>
}
</div>
)
}
export default FetchAPI
Zauważ, jak zwróciliśmy dane lub komunikat o błędzie, w oparciu o odpowiedź w pierwszej funkcji wywołania zwrotnego then. Ważną rzeczą, na którą należy zwrócić uwagę w przypadku fetch API, jest to, że jeśli wystąpi błąd, taki jak 404, funkcja wywołania zwrotnego then zostanie wykonana, a funkcja wywołania zwrotnego wewnątrz catch nie zostanie wykonana. Tak więc, w oparciu o odpowiedź z serwera, musimy albo pobrać dane z odpowiedzi, albo rzucić komunikat o błędzie, który trafia do bloku catch.
W powyższym przykładzie sprawdziliśmy właściwość ok odpowiedzi. Zamiast tego można sprawdzić status odpowiedzi (na przykład 200, 404 lub 500 itp.) i podjąć odpowiednie działania.
Jak używać Fetch API async - await z try - catch w hooku useEffect w aplikacji React?
Innym powszechnie stosowanym sposobem z fetch API jest użycie async i await. Aby obsłużyć błędy, możemy użyć opcji try-catch w naszej aplikacji.
import React, { useState, useEffect } from 'react'
function FetchAPI() {
const [users, setUsers] = useState([])
const [isError, setIsError] = useState(false);
useEffect(() => {
const fetchData = async () => {
try {
let response = await fetch('https://jsonplaceholder.typicode.com/users');
if (response.status === 200) {
let data = await response.json();
setUsers(data);
} else {
throw 'Error fetching users list'
}
} catch (error) {
setIsError(true)
}
}
fetchData();
}, [])
return (
<div>
{isError ? <h3> Error! Please try again later</h3> :
<ul>
{users.map((user) => <li key={user.id} > {user.name} </li>)}
</ul>
}
</div>
)
}
export default FetchAPI
W powyższym przykładzie sprawdziliśmy kod statusu odpowiedzi zamiast właściwości ok, jak to zrobiliśmy w pierwszym przykładzie. Tutaj sprawdziliśmy tylko status 200. W aplikacjach tzw. real-time może być konieczne sprawdzenie również kilku innych kodów statusu, takich jak 201, 404 lub 500 itp.