Hook useCallback - Entenda quando utiliza-lo?
Tags: react, beginners, hooks, javascript
Published: 2022-10-18 01:18:44

Salve Salve! 🖖🏻 Voltei depois de muitoooo tempo 😅. 



Dessa vez vim falar um pouco sobre um dos famosos *hooks* do *React*, *useCallback.* Percebo que ele gera muita dúvida em quem esta iniciando em *React* e até mesmo desenvolvedores que já atuam com ele.

A ideia deste post é apresentar um pouco sobre a minha visão deste *hook* para quem não conhece e esclarecer onde ele pode ser aplicado assim como aplica-lo na pratica. 


_Este é o começo de uma série de posts falando um pouco mais sobre a minha visão sobre os *hooks* disponibilizados pelo *React.*_

![https://media.giphy.com/media/BYS6j7XxxyvTi/giphy.gif](https://media.giphy.com/media/BYS6j7XxxyvTi/giphy.gif)


> **Nota**
*Este post não serve de documentação e não tem como objetivo ser o mais completo possível. Ele representa apenas a minha visão sobre a utilização do useCallback que obtive ao longo do tempo.*

---

## Introdução

A partir do *React 16* foram disponibilizados uma série de *hooks* nativos que buscam facilitar o desenvolvimento de componentes funcionais. Desses *hooks* falaremos neste post sobre *useCallback.*

### useCallback

Este *hook* recebe dois parâmetros, uma função *callback* e um array de dependências. O seu retorno é uma **versão memoizada da função** *callback* recebida como primeiro parâmetro. De forma básica quando me refiro em uma versão memoizada podemos nos referir a uma versão memorizada ou “*cacheada”* da função.


> 
⛳ **Obs:** Aqui vale ressaltar um ponto bem importante, o retorno deste hook é uma versão memoizada da função e não do resultado da função. Isso quer dizer que a função só vai ser executada quando você utiliza-la desta maneira: **minhaFuncao()**


Como este *callback* é uma versão memoizada é preciso informar quando essa função deve ser recalculada para que valores atualizados sejam utilizados. É por isso que existe o array de dependências passado como segundo parâmetro para _hook_. Os valores passado dentro deste array são o que fazem a função *callback* ser recalculada. Normalmente variáveis externas a função de *callback* que são utilizadas dentro da função, estarão neste array. Caso você não informe as variáveis que são utilizadas dentro da função, a grandes chances delas estarem com seus valores desatualizados quando a função for disparada.

Abaixo temos um exemplo da sintaxe deste *hook*:

```jsx
import { useCallback } from 'react';

const handleClick = useCallback(async () => {
	await sendMail(address)
}, [address]);

...

return <button ... onClick={handleSubmit}>Enviar email</button>
```

---
![https://media.giphy.com/media/L3FInpXg6pGEGXPR0a/giphy.gif](https://media.giphy.com/media/L3FInpXg6pGEGXPR0a/giphy.gif)

### Beleza, mas quando utilizar?

Essa é uma pergunta super interessante e importante, porque o uso em excesso ou da maneira incorreta ao utilizar o *useCallback* pode ser pior que utilizar uma simples função comum.

Este *hook* vem pra nos ajudar a melhorar a performance de nossas aplicações mas ao mesmo tempo se utilizarmos de maneira incorreta, estaremos adicionando mais passos/lógicas em nossas funções. Isso porque antes de retornar uma versão *memoizada* da função, o *hook* faz uma comparação para saber se ele deve ou não recalcular aquela versão para então retornar a versão atualizada do callback.

> 
⛳ *Obs: O React já é uma biblioteca muito rápida e eficiente, então em grande parte dos casos, nem iremos notar essas adições de lógicas em nossa aplicação.*

Então voltamos a pergunta, _quando devo utilizar este hook?_ A resposta é apenas uma: **Quando você precisar manter a igualdade referencial.**

Você já deve ter escutado bastante sobre renderizações no universo do *React.* Quando essas renderizações ocorrem sejam por conta que o componente pai alterou, uma propriedade alterou ou algum estado foi alterado, em todos esses casos os componentes em questão entram em processo de renderização. Isso quer dizer que pelo menos uma comparação entre o componente anterior a renderização e o mesmo componente com os dados alterados é realizada.

Nesse processo novos blocos de memória (referências) são utilizados para atualizar variáveis/funções. E aqui entra um grande ponto se você já testou comparações no *Javascript.* Pois ao fazer a seguinte comparação:

```jsx
let a = function(){}
let b = function(){}

a === b // false
```

Isso retornará `false` . Essa comparação apenas será `true` se a referência das funções forem a mesma. Como a gente pode ver abaixo:


![Shallow Compare functions](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/415msqjdgnjg3klci7gr.png)

Podemos notar que apenas quando atribuímos a variável `a` a variável `b` que a comparação entre as duas funções deu `true`. Ou seja, elas utilizam a mesma referência.

Ter noção disso é muito importante porque pode evitar que algumas renderizações desnecessárias ocorram. E isso não vale somente para funções mas também para objetos e arrays.

---
![https://thumbs.gfycat.com/PaleThunderousGroundhog-max-1mb.gif](https://thumbs.gfycat.com/PaleThunderousGroundhog-max-1mb.gif)

### Show me the code! 🤖

Vamos parar de papo e mostrar realmente como você deve utilizar este *hook.* Imagine o seguinte cenário, você tem um hook de autenticação e através dele você disponibiliza duas funções signIn e signOut. Essas funções podem ser envolvidas pelo *useCallback*, isso porque são funções que serão utilizadas em diversos componentes da aplicação e com isso manter a igualdade referencial dessas funções é importante para que se o nosso hook de autenticação for alterado, todos os componentes que o utilizam também serão re-renderizados.

Abaixo tem um exemplo do cenário ilustrado:


![AuthContext](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1wg3scnbi96y1jercf5p.png)

Agora pense em outro cenário: Resolvemos refatorar nosso código e criamos um novo componente para segmentar melhor a lógica. Porém este novo componente terá que atualizar um estado que vai estar em seu componente pai. Para fazer essa atualização, podemos enviar a função que faz essa atualização do pai para o filho e dentro do filho executaríamos esta função passando como parâmetro o valor desejado. 
Este é um uso importante do *useCallback* também. **Funções que são passadas do pai pro filho devem estar envolvidas pelo *hook.*
**
Novamente aqui a principal motivação para seu uso é manter a igualdade referencial da função. Para notarmos 100% isso funcionando na prática, vamos ter que utilizar também outro *hook* do React, o *memo.*

> 
*Obs: Falaremos mais sobre este hook em outro post* 😀

 Abaixo tem um exemplo do cenário ilustrado:


![FatherWithoutCallback](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jdkfqf3g6hpxq5tf1308.png)


O código acima tem como retorno os seguintes consoles ao clicar no botão de *counter:*

![FatherAndChildrenUpdated](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z9yysdlxfzt9r82umivl.png)

Aqui da pra perceber que o “FILHO” só renderizou porque um estado do componente “PAI” foi alterado porém o “FILHO” não recebe o estado que foi alterado. Então você concorda comigo que ele não precisava ser re-renderizado.
Agora se ajustarmos o cenário acima com os *hooks useCallback e memo*, temos o seguinte resultado ao clicar no botão:

![FatherUpdated](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pv8g04bstpcx2rt5wlqw.png)


Agora o componente “FILHO” só renderizará novamente quando a versão *memoizada* da função for atualizada, ou seja, somente quando realmente alguma de suas propriedades alterem. O código com a altera ficou deste jeito:



![FatherToChildWithCallback](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6ocntbcku9hc1xsomz19.png)

---

### Top demais! 😍

Eu espero ter ajudado você a entender um pouquinho mais sobre este *hook,* o que é e quando utilizar. Já passei por essas dúvidas e essas foram as minhas conclusões sobre elas.

Em breve voltarei com outros posts sobre os demais *hooks* que o *React* nos dispõem.

Valeeeeu demais pela leitura! Gostou? Ficou com dúvida? Falei alguma coisa errada? Vamos conversar melhor nos comentários

See you soon! 🖖🏻

![https://media.giphy.com/media/l1J3CbFgn5o7DGRuE/giphy.gif](https://media.giphy.com/media/l1J3CbFgn5o7DGRuE/giphy.gif)

### Referências

- [ReactJS DOC](https://reactjs.org/docs/hooks-reference.html#usecallback)
- [When to useMemo and useCallback](https://kentcdodds.com/blog/usememo-and-usecallback)