Come funziona lo useEffect in React: Esempio pratico
Troverai nel progetto
Che cosa andremo a realizzare:
Il progetto si incentra sull'utilizzo dello useEffect hook per fetchare dei dati ed utilizzarli per mostrare all'utente delle possibili mete turistiche. Utilizzeremo anche lo useState per creare un carosello che permetta all'utente di scorrere tra le varie proposte.
Che cos'è lo useEffect Hook ?
Lo useEffect è l'hook incaricato di gestire i side effects. Ovvero tutte quelle azioni che avvengono all'esterno del componente come: data fetching, subscriptions o modifiche manuali del DOM.
Come si utilizza lo useEffect ?
E' importante precisare che lo useEffect sarà eseguito dopo il render del componente in cui viene definito. E' sempre bene ricordare che gli hooks non possono essere usati in modo condizionale. Questo non vuol dire che al loro interno non si possano implementare logiche condizionali.
const Component = () => { //wrong if(true){ useEffect(() => { }, []) } //...component JSX }
Come possiamo vedere il nostro useEffect hook accetta una callback function come primo parametro e un array come secondo. Questo secondo parametro è molto importante e prende il nome di array di dependencies e definisce in base a quali valori, lo useEffect deve eseguire la callback function che abbiamo passato.
IMPORTANTE: Questo secondo parametro è opzionale e qualora non venisse definito, il nostro hook lancerà la nostra funzione ad ogni re-render del componente. Passarlo come array vuoto indicherà che desideriamo eseguire questa funzione una volta sola. Ma ne parleremo meglio nelle sezioni successive.
Usare useEffect per il data fetching
Uno dei casi d'utilizzo più comuni di questo hook è il fetching dei dati interagendo con un API. Nel nostro progetto infatti verrà usato per fare il render delle nostre card di vacanze, fetchando i dati da un API esterna.
Per prima cosa definiremo una funzione asyncrona:
const getData = async () => { try { const response = await axios.get(url); setData(response.data); } catch (error) { console.log(error); } };
Dopo di che andiamo a richiamare la funzione all'interno del nostro useEffect Hook
useEffect(() => { getData(); }, []);
Come usare al meglio questo hook
Dovremmo gestire al meglio due situazioni
Gestire dinamicamente il caricamento dei dati
Stiamo effettuando una chiamata asyncrona quindi inizialmente non avremo alcun dato da mostrare e con cui interagire. La soluzione più banale è quella di controllare che lo state che data non sia vuoto o falsy e solo in quel caso andare a mostrare i nostri dati.
E' una prassi comune anche utilizzare uno state di loading per controllare che il processo di caricamento sia terminato, uno per gestire l'errore e un altro in cui salvare i nostri dati in casi di success della nostra chiamata
const Component = () => { const [loading, setLoading] = useState(true) const [isError, setIsError] = useState(false) const [data, setData] = useState([]) const getData = async () => { setLoading(true) setIsError(false) try { const response = await axios.get(url); setData(response.data); } catch (error) { setIsError(true) } finally { setLoading(false) } }; useEffect(() => { getData() }, []) if(loading) return <h2>...Loading</h2> if(isError) return <h2>Error</h2> return //Component con data }
Evitare di chiamare all'infinito lo useEffect
E' molto importante quando usiamo questo hook evitare di chiamare all'infinito la nostra funzione getData, altrimenti oltre a litigare con il nostro team backend, faremo crashare l'app facendola entrare in un loop di rendering del componente.
Per evitare questo è fondamentale passare un array di dependencies vuoto come secondo parametro del nostro useEffect. In questo modo indicheremo "a React" che deve il nostro useEffect deve essere eseguito solo una volta.
useEffect e Array di Dependencies
Ma perché dovremmo passare un array di dependencies ? Perché di default l'Effect Hook viene richiamato ad ogni render del componente ed in React anche la modifica di uno state causerà un nuovo render.
Andando noi a modificare lo state di data all'interno della nostra funzione getData ci ritroveremo subito all'interno di un loop infinito che farebbe crashare la nostra applicazione.