Se você está começando a aprender React ou já tem algum tempo usando esta biblioteca, com certeza já se deparou com alguns erros ou warnings relacionados a funções assíncronas, principalmente utilizando o hook useEffect
.
Quando estava aprendendo a funcionalidade desse hook, não conseguia entender o motivo de usar o return nessa função já que na maioria dos casos não é necessário usar, e o React funciona perfeitamente bem sem ele.
À medida que fui me familiarizando mais com o funcionamento do React e o ciclo de vida dos componentes, comecei a perceber que em muitos casos é muito importante usar o return no gancho useEffect
, principalmente nos efeitos colaterais.
Um efeito colateral pode ser buscar dados de um servidor remoto, ler ou gravar no armazenamento local, configurar ouvintes de eventos ou configurar uma assinatura. Esses efeitos colaterais podem ocorrer quando um botão é clicado, um formulário é enviado ou quando um componente é montado e desmontado.
O gancho useEffect
do React permite que os componentes funcionais façam coisas quando um componente é montado ou quando algumas propriedades ou estados mudam. Este gancho também permite a limpeza quando o componente é desmontado.
Lidar com efeitos colaterais no React é uma tarefa de média complexidade. No entanto, de tempos em tempos, você pode ter dificuldades na interseção do ciclo de vida do componente (renderização inicial, montagem, uso, desmontagem) e o ciclo de vida do efeito colateral (iniciado, em andamento, concluído).
Uma dessas dificuldades é quando um efeito colateral é concluído e tenta atualizar o estado de um componente já desmontado.
Isso causa um aviso do React como este:
Vazamentos de memória em aplicativos React são principalmente o resultado de não cancelar assinaturas feitas quando um componente foi montado antes de ser desmontado.
Eles causam muitos problemas, incluindo:
Portanto, é necessário eliminar problemas de vazamento de memória.
É uma função do gancho useEffect
que nos permite parar os efeitos colaterais que não precisam mais ser executados antes que nosso componente seja desmontado.
useEffect
é construído de forma que possamos retornar uma função dentro dele e é nessa função de retorno que acontece a limpeza.
Por exemplo, o Componente A solicita que a API obtenha uma lista de produtos, mas ao fazer essa solicitação assíncrona, o Componente A é removido do DOM (é desmontado). Não há necessidade de concluir essa solicitação assíncrona.
Portanto, como método de limpeza para melhorar seu aplicativo, você pode limpar (cancelar) a solicitação assíncrona para que ela não seja concluída.
useEffect
:
useEffect(() => { // Your effect return () => { // Cleanup } }, [input])
Existem diferentes maneiras de cancelar chamadas de solicitação de busca, podemos usar fetch AbortController
ou Axios AbortController.
Para usar AbortController
, devemos criar um controlador usando o construtor AbortController()
. Então, quando nossa solicitação de busca é iniciada, passamos AbortSignal
como uma opção dentro do objeto de options
da solicitação.
Isso associa o controlador e o sinal à solicitação de busca e nos permite cancelá-la a qualquer momento usando AbortController.abort()
:
useEffect(() => { //create a controller let controller = new AbortController(); (async () => { try { const response = await fetch(API, { // connect the controller with the fetch request signal: controller.signal, }, ); // handle success setList(await response.json()); // remove the controller controller = null; } catch (e) { // Handle the error } })(); //aborts the request when the component umounts return () => controller?.abort(); },[]);
useEffect(() => { // create a controller const controller = new AbortController(); axios .get(API, { signal: controller.signal }) .then({data}) => { // handle success setList(data); }) .catch((err) => { // Handle the error }); //aborts the request when the component umounts return () => controller?.abort(); }, []);
Ao usar as funções de timer setTimeout(callback, time)
, podemos limpá-las ao desmontar usando a função especial clearTimeout(timerId)
.
useEffect(() => { let timerId = setTimeout(() => { // do something timerId = null; }, 3000); // cleanup the timmer when component unmout return () => clearTimeout(timerId); }, []);
Assim como os Timeouts, os setIntervals(callback, time)
têm uma função especial para limpá-los com a função clearInterval(intervalId)
.
useEffect(() => { let intervalId = setInterval(() => { // do something like update the state }, 1000); // cleanup the timer when component unmout return () => clearInterval(interval); }, []);
A limpeza dos ouvintes ocorre por meio de window.removeEventListener
. A chamada removeEventListener
deve fazer referência à mesma função na chamada removeEventListener
para remover o ouvinte corretamente.
useEffect(() => { // function to add to EventListener const handleKeyUp= (event) => { switch (event.key) { case "Escape": setCollapsed(true); break; } } window.addEventListener("keyup", handleKeyUp); // cleanup the listener when component unmout return () => window.removeEventListener("keyup", handleKeyUp); }, []);
Quando você cria umsocket.close()
de limpeza.
useEffect(() => { const ws = new WebSocket(url, protocols) // do what you want with the socket ws.onmessage = (event) => { setValue(JSON.parse(event.data)); }; // cleanup the web socket when component unmout return () => ws.close() }, [])
Aprendemos que alguns efeitos colaterais exigem limpeza para evitar vazamentos de memória e comportamentos desnecessários e indesejados. Devemos aprender quando e como usar a função de limpeza do gancho useEffect
para evitar esses problemas e otimizar os aplicativos.
Eu recomendo limpar os efeitos assíncronos quando o componente é desmontado. Além disso, se o efeito colateral assíncrono depender dos valores prop ou state, considere também limpá-los quando o componente for atualizado.
Espero que você tenha achado este artigo útil e que agora você possa usar o recurso de limpeza corretamente.
Consulte Mais informação:
Publicado também aqui .