Prevenire correttamente il re-rendering di useEffect in React.js
Retroscena
Stavo creando un'app utilizzando Firebase in React e sono stato sorpreso di scoprire che avevo raggiunto il mio limite di 50.000 letture per la giornata. Non riuscivo a capire come diavolo fosse possibile dato che la mia app funziona solo localmente sulla mia macchina ed ero l'UNICO utente.
Il problema che ho dovuto affrontare era correlato al rimontaggio del mio componente durante una chiamata asincrona che modificava la variabile di stato.
Ecco un esempio di un modo scadente per eseguire una chiamata asincrona utilizzando useEffect.
import {useEffect} from 'react'
function Example() {
const [vehicles, setVehicles] = useState([])
const vehiclesRef = collection(db, 'vehicles')
useEffect(() => {
const getVehicles = async () => {
const data = await getDocs(vehiclesRef)
setVehicles(data.docs.map( doc => ( // memory leaks
{
...doc.data(),
id:doc.id
}
)
)
)
}
getVehicles()
},[vehicles])
}
Avviso: non è possibile eseguire un aggiornamento dello stato React su un componente non montato. Si tratta di un errore, ma indica una perdita di memoria nell'applicazione. Per risolvere il problema, annulla tutti gli abbonamenti e le attività asincrone in una funzione di pulizia useEffect.
Quando chiami setState, il tuo componente eseguirà nuovamente il rendering per aggiornare il DOM con le modifiche a quel valore. Ciò significa che setVehicles()continuerà l'inizializzazione ogni volta che il componente viene montato. Ciò causerà un ciclo infinito di re-rendering, che ti costerà un sacco di soldi quando effettui chiamate di funzioni costose.
Ecco come l'ho risolto.
import {useEffect, useRef} from 'react'
function Example() {
const [vehicles, setVehicles] = useState([])
const vehiclesRef = collection(db, 'vehicles')
useEffect(() => {
let isMounted = true
const getVehicles = async () => {
const data = await getDocs(vehiclesRef)
if(isMounted){
setVehicles(data.docs.map( doc => (
{
...doc.data(),
id:doc.id
}
)
)
)
}
}
getVehicles()
console.log(vehicles)
return () => { isMounted = false }
}, [vehicles])
}
Quando isMounted is false, il codice non verrà eseguito finché tale valore non viene impostato su true, quando il componente viene nuovamente montato.
Spero che questo ti aiuti!
Codifica di livello superiore
Grazie per far parte della nostra comunità! Prima che tu vada:
- Batti le mani per la storia e segui l'autore
- Visualizza altri contenuti nella pubblicazione Level Up Coding
- Seguici: Twitter | Linkedin | Notiziario

![Che cos'è un elenco collegato, comunque? [Parte 1]](https://post.nghiatu.com/assets/images/m/max/724/1*Xokk6XOjWyIGCBujkJsCzQ.jpeg)



































