React Hook – Clean Up useEffect

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!

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *