Renderização no React + useEffects
Tags: react, javascript
Published: 2023-05-21 20:29:07

Antes de tudo, é importante ressaltar: Ninguém usa mais Componentes de Classe no React, portanto, esse post é sobre renderização de Componentes Funcionais.

## Componente Funcional
Um componente funcional é basicamente uma função que retorna um `JSX.Element`, isto é, tags HTML com uma pitada de JavaScript.

Para declarar e exportar um componente funcional no React, basta declarar e exportar uma **função**.

Supondo que você saiba como funciona o `useState` (Se não souber, avise nos comentários), é assim que se declara um component funcional _com estado_ no React:

``` react
import React, { useState } from "react"

export const Contador = () => {
  const [valorContador, atualizaValorContador] = useState(0)
  const aumentaValor = () => {
    atualizaValorContador(valorContador + 1)
  }

  return (
    <button id="value-button" onClick={aumentaValor}>
      { valorContador }
    </button>
  )
}
```

Você também pode declarar um componente funcional utilizando a palavra-chave `function` ao invés de `const`:

``` react
export function Contador() {
  const [valorContador, atualizaValorContador] = useState(0)
  const aumentaValor = () => {
    atualizaValorContador(valorContador + 1)
  }

  return (
    <button id="value-button" onClick={aumentaValor}>
      { valorContador }
    </button>
  )
}
```

## Renderização
> Sempre que um estado ou propriedade do componente mudar, o código da função será executado novamente.

É crucial que você entenda 100% da frase acima, anote-a caso necessário.

Isso significa que a cada clique no 'value-button':

- O _valorContador_ será incrementado.
- A função _aumentaValor_ será redeclarada, criando uma nova referência na memória.
- O bloco _return_ será executado novamente.

Ou seja, todo código da função é executado novamente!

## Hook useEffect
O hook useEffect é uma função disponível no React que permite a execução de efeitos colaterais (side-**effects**) em componentes funcionais. 

Através de uma "manobra" do _EventLoop_ (um pouco complexo de explicar), o contexto da função roda em um estado "non-blocking", ou seja, não atrapalha na renderização do componente.

Quase como se rodasse em uma thread separada, mas não roda.

- A função é executada após a renderização do componente.
- Você controla _quando_ o _efeito_ será executado através meio de uma lista de dependências, passada como segundo parâmetro da função **useEffect**.

Agora, para demonstrar seus casos de uso, vamos supor que queremos exibir um alerta na página.

### Roda sempre (Sem dependência)
Para adicionar um "side-effect" sempre que houver qualquer alteração de estado ou de propriedade no componente, basta utilizar o `useEffect` sem um segundo parâmetro.

``` react
useEffect(() => {
  alert('Eu sou executado sempre que o componente é renderizado')
}) 
```

### Roda 1x
Rodar uma função a TODA atualização de QUALQUER _estado_ OU _prop_ é, na maioria das vezes, desnecessário.

Caso você queira executar uma função apenas 1x, logo após o componente ter sido renderizado, você deve utilizar o `useEffect` da seguinte maneira.

``` react
useEffect(() => {
  alert('Eu sou executado uma vez, depois que o componente é renderizado pela primeira vez')
}, [])
```

### Roda sempre que [estado1, estado2] mudarem
Para efeitos colaterais específicos vinculados a um ou mais estados, você pode adicionar os estados desejados ao **array de dependências** do `useEffect`.

``` react
useEffect(() => {
  alert('Eu sou executado sempre que o valorContador mudar.')
  console.log(valorContador)
}, [valorContador])
```

Isso é especialmente útil quando você possui mais de um estado em um componente e quer atribuir ações específicas às suas atualizações.

Por via de regra, é uma boa prática incluir apenas os estados utilizados na função callback (primeiro parâmetro) no array de dependências.

Tenha cuidado com o cenário "sem dependências", pois isso pode levar a execuções desnecessárias e problemas de performance.

Fique ligado para mais posts sobre renderização no React, onde pretendo abordar os hooks **useCallback** e **useMemo** em breve!