Matheus Goes

O que sao React Hooks ?

20 de dezembro de 2023

Introdução aos React Hooks mais utilizados: useState & useEffect

Matheus Goes

Matheus Goes

Frontend
Matheus Goes

Faaala dev, como esta? Bora entender o porque da biblioteca ReactJS ser tao famosa e ser a mais em alta no mercado, aprendendo um pouco sobre os React hooks!

Trazida na versao 16.7.0, o ReactJs basicamente oferece formas de trabalharmos com o estado e outras APIs sem a necessidade de criarmos classes (stateful component). Entao bora começar entendendo o que e um Hook?


Bora entender o porque da biblioteca ReactJS ser tao famosa e ser a mais em alta no mercado, aprendendo um pouco sobre os React hooks!

Trazida na versao 16.7.0, o ReactJs basicamente oferece formas de trabalharmos com o estado e outras APIs sem a necessidade de criarmos classes (stateful component). Entao bora começar entendendo o que e um Hook?

Um Hook é uma função especial que te permite utilizar recursos do React. Por exemplo, useState é um Hook que te permite adicionar o state do React a um componente de função. Vamos aprender outros Hooks mais tarde.

Quando eu deveria usar um Hook? Se você escreve um componente de função e percebe que precisa adicionar algum state para ele, anteriormente você tinha que convertê-lo para uma classe. Agora você pode usar um Hook dentro de um componente de função existente. Vamos fazer isso agora mesmo!

useState

Declarando uma Variável State

Blog post image

O que o hook useState faz? Ele declara um variável state. Nossa variável é chamada de count mas poderíamos chamar de qualquer coisa, como banana. Esta é uma maneira de “preservar” alguns valores entre as chamadas de funções — useState é uma nova maneira de usar as mesmas capacidades que o this.state tem em uma classe. Normalmente, variáveis “desaparecem” quando a função sai mas variáveis de state são preservadas pelo React.

O que passamos para useState como argumento? O único argumento para o Hook useState() é o state inicial. Diferente de classes, o state não tem que ser um objeto. Podemos manter um número ou uma string se for tudo que precisamos. No nosso exemplo, apenas queremos um número para quantas vezes o usuário clicou, então passamos 0 como state inicial para nossa variável. (Se quiséssemos guardar dois valores diferentes no state, chamaríamos useState() duas vezes.)

O que o useState retorna? Ele retorna um par de valores: o estado atual e uma função que o atualiza. É por isso que declaramos:

const [count, setCount] = useState().

Isto é similar ao this.state.count e this.setState em uma classe, exceto o fato de pegá-los em par.

Lendo a variavel state

Em uma função, podemos usar o count diretamente

<p>Você clicou {count} vezes</p>

Atualizando a variável state

Na função, já temos setCount e count como variáveis então não precisamos do this:

Blog post image

Resumindo tudo de forma facil:

Blog post image
  • Linha 1: Importamos o Hook useState do React. Ele nos permite manter o state local em um componente de função.
  • Linha 4: Dentro do componente Example, declaramos uma nova variável de state chamando o Hook useState. Ele retorna um par de valores, no qual damos nomes. Estamos chamando nossa variável count porque ela mantém o número de cliques no botão. Inicializamos como zero passando 0 como o único argumento do useState. O segundo item retornado é a própria função. Ela nos permite atualizar o count então nomeamos para setCount.
  • Linha 9: Quando o usuário clica, chamamos setCount com um novo valor. O React então vai re-renderizar o componente Example, passando o novo valor de count para ele.

À primeira vista pode parecer muita coisa. Não se preocupe! Se você está perdido na explicação, olhe o código acima novamente e tente lê-lo de uma ponta a outra. Prometemos que a partir do momento que você “esquecer” como state funciona em classes e olhar este código com novos olhos irá fazer sentido. e na minha opinião, e muito mais fácil de entender state do que classes (Obrigado ReactJs pela constante evolução)

Usando Múltiplas Variáveis State

Declarar variáveis de state como par de [something, setSomething] também é útil porque nos permite dar diferentes nomes para diferentes variáveis de state se quiséssemos usar mais de uma:

Blog post image

No componente acima, temos age, fruit e todos como variáveis locais e podemos atualizá-las individualmente:

Você não tem que usar muitas variáveis de state. Elas podem conter objetos e arrays muito bem. Portanto você ainda pode juntar dados relacionados. De qualquer maneira, ao atualizar uma variável de state, ela sempre é substituída ao invés de incorporada.

useEffect

O Effect Hook (Hook de Efeito) te permite executar efeitos colaterais em componentes funcionais:

Blog post image

Esse trecho de código é baseado no exemplo de contador acima, mas nós adicionamos uma nova funcionalidade a ele: nós definimos o título do documento para ser uma mensagem customizada que inclua o número de cliques.

Buscar dados, configurar uma subscription, e mudar o DOM manualmente dentro dos componentes React são exemplos de efeitos colaterais. Esteja você acostumado ou não a chamar essas operações de “efeitos colaterais” (ou somente “efeitos”), você provavelmente já usou eles em seus componentes antes.

Dica
Se você está familiarizado com os métodos do ciclo de vida do React, você pode pensar no Hook useEffect como componentDidMount, componentDidUpdate, e componentWillUnmount combinados.

O que o useEffect faz? Usando esse Hook, você diz ao React que o componente precisa fazer algo apenas depois da renderização. O React ira se lembrar da função que você passou (nos referiremos a ele como nosso “efeito”), e chamá-la depois que realizar as atualizações do DOM. Nesse efeito, mudamos o título do documento, mas podemos também realizar busca de dados ou chamar alguma API imperativa.

Por que useEffect é chamado dentro de um componente? Colocando useEffect dentro do componente nos permite acessar o state count (ou qualquer outra prop) direto do efeito. Nós não precisamos de uma API especial para lê-los — já está no escopo da função. Hooks adotam as closures do JavaScript e evitam APIs especificas do React onde o JavaScript já provê uma solução.

useEffect executa depois de toda renderização? Sim! Por padrão, ele roda depois da primeira renderização e depois de toda atualização. (Falaremos sobre como customizar isso depois.) Em vez de pensar em termos de “montando” (“mounting”) e “atualizando” (“updating”), você pode achar mais fácil pensar que efeitos acontecem “depois da renderização”. React garante que o DOM foi atualizado na hora de executar os efeitos.

Explicação detalhada

Agora que já sabemos mais sobre os efeitos, essas linhas devem fazer sentido:

Blog post image

Declaramos o state count, e então dizemos ao React que precisamos usar um efeito. Passamos uma função para o Hook useEffect. Essa função que passamos é o nosso efeito. Dentro do nosso efeito, definimos o título do documento usando document.title da API do navegador. Podemos ler o último count dentro do nosso efeito por que ele está dentro do escopo da nossa função. Quando o React renderizar nosso componente, ele ira se lembrar do efeito que usamos, e então executar os nossos efeitos depois de atualizar o DOM. Isso acontece para cada renderização, incluindo a primeira.

Desenvolvedores JavaScript experientes podem perceber que a função passada para o useEffect vai ser diferente a cada renderização. Isso é intencional. Na verdade, isso é o que nos deixa ler o valor de count de dentro do efeito sem nos preocuparmos com ele ficar obsoleto. Toda vez que nós re-renderizarmos, agendamos um efeito diferente, substituindo o antigo. De uma maneira, isso faz os efeitos se comportarem mais como o resultado da renderização — cada efeito “pertence” à sua renderização especifica.

Efeitos Com Limpeza

Anteriormente, nós vimos como expressar efeitos colaterais que não precisam de limpeza. Contudo, alguns efeitos precisam. Por exemplo, nós podemos querer configurar uma subscription para alguma origem de dados externa. Nesse caso, é importante limpar para que não causemos um vazamento de memória! Vamos comparar como faríamos isso com classes e com Hooks.

Vamos ver como poderíamos escrever esse componente usando Hooks.

Você pode pensar que precisamos de um efeito separado para executarmos a limpeza. Mas o código para adicionar e remover uma subscription é tão relacionado um com o outro que o useEffect foi desenhado para mantê-los juntos. Se o seu efeito retornar uma função, o React irá executá-la quando for a hora de limpar:

Blog post image

Por que precisamos retornar uma função dos nossos efeitos? Isso é um mecanismo opcional de limpeza para efeitos. Cada efeito pode retornar uma função que irá limpar depois dela. Isso nos permite manter a lógica para adicionar e remover subscriptions perto uma da outra. Elas são parte do mesmo efeito!

Quando exatamente o React limpa um efeito? O React executa a limpeza quando o componente desmonta. Contudo, como aprendemos anteriormente, efeitos rodam em todas as renderizações e não apenas uma vez. É por isso que o React também limpa os efeitos da renderização anterior antes de rodar os efeitos da próxima vez

Nota
Nós não precisamos retornar uma função nomeada do efeito. Nós chamamos de cleanup aqui apenas para esclarecer seu propósito, mas nós podemos retornar uma arrow function ou chamarmos de qualquer coisa diferente.

Dica: Otimizando a Performance ao Pular Efeitos

Em alguns casos, limpar ou aplicar o efeito em cada renderização pode criar um problema de performance. Esse requerimento é comum o bastante para estar embutido na API do Hook useEffect. Você pode dizer ao React para pular a aplicação de um efeito se certos valores não tiverem mudado entre as renderizações. Para fazer isso, passe uma array como um segundo argumento opcional ao useEffect:

Blog post image

No exemplo acima, nós passamos o [count] como segundo argumento. O que isso quer dizer? Se count é 5, e o nosso componente re-renderiza com count ainda sendo 5, o React irá comparar [5] da renderização passada e [5] da próxima renderização. Por todos os itens na array serem o mesmo (5 === 5), o React ira pular o efeito. Essa é a nossa otimização.

Quando nós renderizamos com count atualizado para 6, o React irá comparar os itens no array [5] da renderização passada com os items no array [6] da próxima renderização. Desta vez, o React irá re-aplicar o efeito porque 5 !== 6. Se houver múltiplos itens no array, o React irá re-executar o efeitos mesmo se apenas um deles for diferente.

Isso também funciona para efeitos que tenham uma fase de limpeza:

Blog post image

Lembre-se que sempre que estiver aprendendo algo novo, a sua melhor amiga e a documentação!

E chegamos ao fim dessa pequena grande introdução aos 2 principais hooks do Reactjs!

Que a força esteja com você!


Feedback
Curtiu o artigo? Me manda um feedback no Instagram para que eu possa sempre melhorar! 🚀

Receba atualizações de novos artigos, guias e dicas direto na sua inbox. Inscreva-se!