Em nosso último artigo aprendemos sobre ações assíncronas sobre useEffect e o seu uso correto (React Hook – Async funcion em useEffect).
Hoje vamos ver como usar a função de limpeza do useEffect React Hook.
Quando você atualizar um estado de um componente não montado, React lançará esse erro:
” Can’t perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in the componentWillUnmount method.”
useEffect(() => { //Faça todo o trabalho, por exemplo, assinar um canal websocket return function (){ //Cancelar inscrição ao canal websocket }; }, []);
Impedir a atualização do componente não montado:
Aqui você vai aprender a evitar esse problema
useEffect(() => { let isCancelled = false; const runAsync = async () => { try { if (!isCancelled) { // Faça oque tem que ser feito } } catch (e) { if (!isCancelled) { throw e; } } }; runAsync(); return () => { isCancelled = true; }; }, [...]);
Uso com setInterval/setTimeout:
Esta é uma boa solução para abortar setInterval / setTimeout:
useEffect(() => { const interval = setInterval(() => { console.log('Cinco Segundos!'); }, 5000); return () => clearInterval(interval); }, []);
Imagine este caso de uso: você abriu um determinado componente e, em seguida o fechou. Se você não limpar o timeout/interval, vai continuar executando o callback.
Uso com o Banco de Dados em Tempo Real da Firestore:
Isso é útil ao usar o Firestore Realtime Database:
useEffect(() => { //Inscrição: canal no firebase const cleanUp = firebase.firestore().collection('photos') .doc(id) .onSnapshot( doc => { setLoading(false); setPhotos(doc) }, err => { setError(err); } ); return () => cleanUp(); //Cancelar inscrição }, []);
Se você esqueceu de limpar suas inscrições, você pode receber solicitações desnecessárias.
Uso com fetch + AbortController:
Cancele requisição fecth com abortcontroller:
useEffect(() => { const abortController = new AbortController(); const fetchData = async () => { try { const ret = await fetch("/companies", { signal: abortController.signal }); const data = await ret.json(); // ... } catch(error) { if (abortController.signal.aborted) { // cancelado } else throw error; }; }; fetchData(); return () => abortController.abort(); }, [companies]);
Uso com axios request:
Veja como cancelar requisições do axios.
useEffect(() => { const source = axios.CancelToken.source(); const fetchData = async () => { try { const response = await Axios.get("/companies", { cancelToken: source.token }); // ... } catch (error) { if (Axios.isCancel(error)) { //cancelado } else { throw error; } } }; fetchData() return () => { source.cancel(); }; }, [companies]);
A função useEffect é o equivalente a componenteDidMount em um componente de Classe React.
A função de Clean Up é o equivalente ao componenteWillUnmount em um componente de Classe React.
Próximo artigo: React – As diferenças entre componentes de classe e componentes de função.
Até logo!