Compreendendo as Diferenças entre useEffect, useMemo e useCallback
Published: 2023-09-07 15:17:06

## Mas, o que é um Hook?
No React, um hook é uma função especial que permite que você "ligue-se" a recursos e funcionalidades do React em componentes funcionais. Os hooks foram introduzidos no React 16.8 para permitir o uso de estados e outros recursos anteriormente disponíveis apenas em componentes de classe em componentes funcionais.
Os hooks permitem que você adicione funcionalidades de gerenciamento de estado, efeitos colaterais, contexto, referências e muito mais aos seus componentes funcionais.
Neste artigo, abordaremos as distinções entre três hooks essenciais do React: **useEffect**, **useMemo** e **useCallback**.

## useEffect

O **useEffect** trata principalmente de lidar com efeitos colaterais em componentes React. Efeitos colaterais geralmente incluem operações como buscar dados, manipular o DOM e gerenciar assinaturas. Aqui está uma análise das suas principais características:

1. Propósito: O propósito principal do **useEffect** é executar código que tenha efeitos colaterais. Esses efeitos colaterais podem estar relacionados à renderização do componente ou a mudanças em suas dependências.

2. Uso: Você fornece uma função de retorno para o **useEffect**, e o React executa essa função depois que o componente foi renderizado ou quando as dependências especificadas foram alteradas.

3. Casos de Uso Típicos: O **useEffect** é comumente utilizado para tarefas como buscar dados, configurar e limpar ouvintes de eventos e realizar ações em resposta a mudanças em props ou estado.

### Exemplo de Uso

```
import React, { useState, useEffect } from 'react';

function ExemploUseEffect() {
  // Defina um estado para armazenar uma contagem
  const [count, setCount] = useState(0);

  // useEffect é usado para realizar efeitos colaterais
  useEffect(() => {
    // Atualize o título da página com a contagem atual
    document.title = `Contagem: ${count}`;

    // Este código será executado após cada renderização
    // e sempre que 'count' for alterado.

    // É uma boa prática retornar uma função de limpeza
    // se você precisar desfazer algum efeito.
    return () => {
      document.title = 'Aplicação React'; // Reverter o título
    };
  }, [count]); // Especifique as dependências aqui

  return (
    <div>
      <p>Contagem: {count}</p>
      <button onClick={() => setCount(count + 1)}>Incrementar</button>
    </div>
  );
}

export default ExemploUseEffect;
```
Neste exemplo, usamos o **useEffect** para atualizar o título da página com a contagem atual toda vez que o estado count for alterado. Observamos que passamos [count] como um segundo argumento para o useEffect. Isso especifica as dependências do efeito, ou seja, quando o efeito deve ser executado novamente. Neste caso, o efeito será acionado sempre que count mudar.

Além disso, fornecemos uma função de retorno no **useEffect**. Esta função será chamada quando o componente for desmontado ou quando a dependência count mudar novamente. É uma prática recomendada para fazer a limpeza de efeitos quando eles não são mais necessários.

Quando você clicar no botão "Incrementar", a contagem aumentará e o título da página será atualizado de acordo com o valor atual da contagem.

## useMemo

O useMemo é inteiramente voltado para a memorização. A memorização é uma técnica na qual o resultado de uma função ou expressão custosa é armazenado em cache, de modo que seja recalculado apenas quando suas dependências mudam. Aqui está uma análise das suas principais características:

1. Propósito: O **useMemo** é usado para memorizar (armazenar em cache) o resultado de uma função ou expressão. Isso pode melhorar o desempenho ao evitar cálculos desnecessários.

2. Uso: Você fornece uma função e uma matriz de dependências para o **useMemo**. O React executa a função e armazena em cache seu resultado. Se as dependências mudarem, a função é reexecutada e o resultado é atualizado.

3. Casos de Uso Típicos: A memorização é útil para cálculos computacionalmente custosos ou para evitar renderizações desnecessárias de componentes.

### Exemplo de Uso

```
import React, { useState, useMemo } from 'react';

function ExemploUseMemo() {
  // Defina dois estados para armazenar números
  const [num1, setNum1] = useState(5);
  const [num2, setNum2] = useState(10);

  // Use useMemo para calcular a soma dos números apenas quando eles mudarem
  const soma = useMemo(() => {
    console.log('Calculando a soma...');
    return num1 + num2;
  }, [num1, num2]); // Dependências

  return (
    <div>
      <p>Número 1: {num1}</p>
      <p>Número 2: {num2}</p>
      <p>Soma: {soma}</p>
      <button onClick={() => setNum1(num1 + 1)}>Incrementar Número 1</button>
      <button onClick={() => setNum2(num2 + 1)}>Incrementar Número 2</button>
    </div>
  );
}

export default ExemploUseMemo;
```
Neste exemplo, estamos usando o **useMemo** para calcular a soma dos números num1 e num2. O cálculo da soma é uma operação simples, mas suponha que tivéssemos uma operação computacionalmente cara em vez disso.

O **useMemo** recebe uma função de cálculo e uma matriz de dependências como argumentos. A função de cálculo será executada apenas quando uma das dependências (num1 ou num2) mudar. Isso significa que a soma só será recalculada quando um dos números for incrementado.

Dentro da função de cálculo, você pode realizar qualquer operação que desejar. Neste exemplo, usamos um console.log para demonstrar quando a soma está sendo calculada.

Ao clicar nos botões "Incrementar Número 1" ou "Incrementar Número 2", apenas o número relevante é atualizado, e a soma é recalculada somente quando necessário, graças ao uso do useMemo. Isso ajuda a evitar cálculos desnecessários e melhora o desempenho do componente.

## useCallback

O **useCallback** está intimamente relacionado ao **useMemo**, mas foca na memorização de funções em vez de valores. É particularmente útil ao passar funções de retorno de chamada para componentes filhos. Aqui está uma análise das suas principais características:

1. Propósito: **useCallback** é usado para memorizar (armazenar em cache) uma função de modo que ela seja recriada apenas quando suas dependências mudam. Isso pode otimizar o desempenho ao passar funções de retorno de chamada como propriedades.

2. Uso: Você fornece uma função e uma matriz de dependências para **useCallback**. O React retorna uma versão memorizada da função. Se as dependências mudarem, uma nova função memorizada é criada.

3. Casos de Uso Típicos: É comumente usado para memorizar funções de retorno de chamada, especialmente ao passar essas funções para componentes filhos.

### Exemplo de Uso

```
import React, { useState, useCallback } from 'react';

function ExemploUseCallback() {
  // Defina um estado para armazenar um contador
  const [contador, setContador] = useState(0);

  // Defina uma função de retorno de chamada para incrementar o contador
  const incrementarContador = useCallback(() => {
    setContador(contador + 1);
  }, [contador]); // Dependência: contador

  return (
    <div>
      <p>Contador: {contador}</p>
      <button onClick={incrementarContador}>Incrementar Contador</button>
    </div>
  );
}

export default ExemploUseCallback;
```
Neste exemplo, estamos usando o **useCallback** para memorizar a função **incrementarContador**. A função **incrementarContador** simplesmente incrementa o valor do contador quando o botão é clicado.

Observe que passamos [contador] como uma matriz de dependência para **useCallback**. Isso significa que a função **incrementarContador** será memorizada e recriada apenas quando a dependência contador mudar. Isso é útil para evitar que a função seja recriada em cada renderização, economizando recursos.

Ao clicar no botão "Incrementar Contador", o valor do contador aumenta, e a função incrementarContador é chamada sem ser recriada desnecessariamente. Isso melhora a eficiência e é particularmente útil ao passar essa função como propriedade para componentes filhos, onde a memorização pode economizar ciclos de renderização.

## Principais Diferenças

1. **useEffect** é usado para lidar com efeitos colaterais e executar código após a renderização ou quando certas dependências mudam.

2. **useMemo** é usado para memorizar o resultado de uma função ou expressão a fim de evitar recalculos desnecessários.

3. **useCallback** é usado para memorizar funções, sendo especialmente útil para otimizar componentes filhos que dependem de funções de retorno de chamada.

Todos os três hooks recebem uma matriz de dependências. Quando essas dependências mudam, **useEffect** executa sua função de efeito, **useMemo** recalcula o valor e **useCallback** recria a função memorizada.

Em resumo, esses hooks têm propósitos distintos e são ferramentas valiosas para gerenciar diferentes aspectos dos seus componentes React. Compreender quando e como usar **useEffect**, **useMemo** e **useCallback** podem contribuir para tornar seus aplicativos React mais eficientes e tornar a
manutenção mais simples.

## Referências

- [Documentação React](https://react.dev/reference/react)

- [Documentação useEffect](https://react.dev/reference/react/useEffect)

- [Documentação useMemo](https://react.dev/reference/react/useMemo)

- [Documentação useCallback](https://react.dev/reference/react/useCallback)