⚛Os 10 React Hooks Mais Úteis: 06 - useCallback⚛
Tags: react, javascript, webdev, beginners
Published: 2023-01-01 23:04:59

_Este é o sexto artigo de uma série de 10, que explica de forma simplificada e com exemplos, os react hooks mais utilizados em programação._
<br>
O `useCallback` é um hook do React que retorna uma função memorizada. Isso significa que a função **só é recriada quando uma de suas dependências mudar.**

Caso contrário, a mesma instância de função é retornada em todas as chamadas.

O `useCallback` é útil quando você tem um componente que precisa passar uma função para um componente filho ou para uma função de gancho, mas quer evitar que a função seja recriada toda vez que o componente pai é renderizado. Isso pode ajudar a **evitar o ciclo de atualização de componentes indesejado** e **aumentar a performance de sua aplicação**.

---

## Como usar o useCallback
Aqui está um exemplo da funcionalidade do `useCallback`:
_`(Acompanhe em "Show files>src>App.jsx")`_
{% embed https://replit.com/@MarceloPetry/Contador-useCallback?v=1 %}

O código acima é de uma função chamada `App` que usa o hook `useState` para gerenciar o estado de uma variável chamada `count`. Ele também cria duas funções memorizadas usando o hook `useCallback: increment` e `reset`. 

A função `increment` é criada usando o `useCallback` com uma lista de dependências contendo apenas a variável `count`. Isso significa que a função só será recriada quando o valor de `count` mudar. A função `increment` é usada como um manipulador de cliques para um botão e, quando clicada, incrementa o valor de `count` em 1. 

A função `reset` é criada de maneira semelhante, usando o `useCallback` com uma lista de dependências contendo apenas a variável `count`. Isso significa que a função só será recriada quando o valor de `count` mudar. A função `reset` é usada como um manipulador de cliques para outro botão e, quando clicada, define o valor de `count` como 0. 

O objetivo do `useCallback` é garantir que as funções `increment` e `reset` sejam criadas **apenas quando necessário**, evitando que elas sejam recriadas toda vez que o componente é renderizado. Isso pode ajudar a **evitar o ciclo de atualização de componentes indesejado** e **aumentar a performance de sua aplicação**.
<br>
### Filtro de lista com useCallback em React
Um uso comum do `useCallback` é no caso em que você tem uma lista e pretende realizar uma busca instantânea nos items dessa lista.

O exemplo abaixo demonstra como implementar um filtro de lista de Pokémons através desse hook:
_`(Acompanhe em "Show files>src>App.jsx")`_

{% embed https://replit.com/@MarceloPetry/Filter-with-useCallback?v=1 %}

1 - A primeira chamada a `useState` inicializa a variável de estado `users` com uma lista de objetos de Pokémon e retorna essa lista e a função `setUsers`.

2 - `useState` é chamado novamente para inicializar a variável de estado `filter` com uma string vazia e retornar essa string e a função `setFilter`. 

3 - A função `handleFilterChange` é criada usando `useCallback` e só será recriada se o valor de `filter` mudar. A função `handleFilterChange` é chamada como um manipulador de evento `onChange` de entrada e atualiza o valor de `filter` com o valor da entrada.

4 - `useCallback` é chamado novamente para criar a função `filteredUsers`, que filtra a lista de pokémons (users) com base no valor de `filter`. A função `filteredUsers` só será recriada se o valor de `users` ou `filter` mudar. 

5 - O componente `App` renderiza uma entrada de pesquisa, um botão de reset de filtro e o componente filho `ChildComponent`. O valor atual de `filter` é passado como o valor da entrada de pesquisa e a função `handleFilterChange` é passada como o manipulador de evento `onChange`. O componente filho é passado a função `filteredUsers` como uma propriedade, que é usada para renderizar uma lista de cards de Pokémon filtrados. 

6 - O componente filho `ChildComponent` renderiza uma lista de cards de Pokémon usando a propriedade `users`, que é uma função de callback passada pelo componente pai. Cada card é composto por uma foto do Pokemon correspondente e seu nome. A foto é exibida através de uma tag `img` e a URL da imagem é obtida da propriedade `image` do objeto Pokémon. O nome do Pokémon é exibido através de uma tag `p`. Cada card é exibido em uma lista através de uma tag `li`. Quando o usuário digita algum valor no input de busca, a função `handleFilterChange` é chamada para atualizar o valor do filtro. A função `filteredUsers`, que é criada com o `useCallback`, é usada para filtrar a lista de Pokémons com base no valor atual do filtro.

7 - A lista de Pokémons filtrados é passada como propriedade para o componente filho `ChildComponent` e é exibida através de uma lista. Ao clicar no botão "Reset filter", o filtro é resetado para vazio, exibindo novamente todos os Pokémons.
<br>
## Hook useCallback para evitar a recriação de funções em componentes React

O hook `useCallback` do React permite que uma função seja retornada de forma **imutável**, **evitando sua recriação** a cada renderização do componente pai. Isso pode ser útil em situações em que uma função é passada como propriedade para um componente filho e pode **melhorar a performance da aplicação**.

Abaixo, temos um exemplo de código que evita a recriação de funções, o qual continua no caso anterior (lista com pokémons):
_`(Acompanhe em "Show files>src>App.jsx")`_
{% embed https://replit.com/@MarceloPetry/Detail-Expand-Pkmn-with-useCallback#src/App.jsx %}

1 - `import "./App.css"` importa o arquivo de estilo `App.css` para o componente `App`. 

2 - `import { useState, useCallback } from "react"` importa os hooks `useState` e `useCallback` do pacote `react`. 

3 - `function App()` define o componente `App`. 

4 - `const [selectedType, setSelectedType] = useState(null)` define o estado `selectedType` como `null` e uma função `setSelectedType` para atualizar o estado. 

5 - `const [pokemons, setPokemons] = useState([{ id: 1, name: "Abra", type: "psychic" }, { id: 2, name: "Bellsprout", type: "grass" }, { id: 3, name: "Chansey", type: "normal" }])` define o estado `pokemons` como um array de objetos e uma função `setPokemons` para atualizar o estado. 

6 - `const handleSelectType = useCallback((type) => { setSelectedType(type) }, [selectedType])` cria uma função de callback chamada `handleSelectType` usando `useCallback`. A função atualiza o estado `selectedType` com o argumento `type` passado para ela. O segundo argumento para `useCallback` é um array de dependências, no caso apenas o valor de `selectedType`. Isso significa que, se o valor de `selectedType` não mudar, a mesma instância de `handleSelectType` será retornada e pode ser reutilizada sem que o componente seja renderizado novamente. 

7 - `return (...)` retorna JSX que renderiza uma lista de Pokemon e um componente `DetailsComponent`, se `selectedType` tiver um valor. 

8 - `function DetailsComponent({ selectedType })` define o componente `DetailsComponent` que recebe `selectedType` como um prop. 

9 - `return <div className="type"> Pokemon do tipo: {selectedType}
` retorna JSX que renderiza o texto "Pokemon do tipo: [selectedType]". 

10 - `export default App` exporta o componente `App` para ser usado em outros arquivos.

Em resumo, o `useCallback` no código acima é usado para criar uma função de callback chamada `handleSelectType` que é passada como um prop para um componente filho.

Quando os argumentos passados para `useCallback` (no caso, apenas o valor de `selectedType`) não mudam, a mesma instância de `handleSelectType` é retornada e pode ser reutilizada pelo componente filho sem que ele seja renderizado novamente. Isso pode ser útil para evitar que um componente filho seja renderizado desnecessariamente, pois a função de callback não mudou.

---

## Conclusão

O hook `useCallback` do React é uma ferramenta útil para **evitar a recriação de funções a cada renderização** de um componente, o que garante uma **melhor performance** à aplicação.

Além disso, ao retornar uma função imutável, o `useCallback` garante que a função passada como propriedade para um componente filho não mude a cada renderização do componente pai, o que pode ser apropriado em casos em que seja importante garantir a consistência do comportamento da função.

Em suma, o hook `useCallback` é uma ferramenta valiosa para **garantir a eficiência e otimização** de aplicações React.