Conhecendo o que é o ciclo de vida de um componente

Descrevendo um componente da forma mais básica possível, podemos dizer que é um pedaço de código que é renderizado para o usuário, que pode ser atualizado caso haja alguma interação, e que pode deixar de ser renderizado.

Por essa razão, cada componente possui um ciclo de vida, que vai da fase de montagem até a fase de desmontagem (destruição). Vejamos na Figura 1 quais são essas fases do ciclo de vida de um componente.

ciclo de vida de um componente
Figura 1. Ciclo de vida de um componente
  1. Primeiramente o componente é configurado, o que chamamos de INICIALIZAÇÃO.
  2. Depois acontece a MONTAGEM, que é quando o componente é renderizado pela primeira vez.
  3. Em seguida, caso necessário, esse componente pode ser atualizado (ATUALIZAÇÃO).
  4. E, por fim, quando por algum motivo ele precisar "sumir", acontece a DESMONTAGEM.

Antigamente, o ciclo de vida era feito exclusivamente através da sintaxe de classe, porém com a chegada dos Hooks no React a partir da versão 16.8, agora conseguimos utilizar o hook useEffect para fazer o processo de controle do ciclo de vida de um componente. Vejamos mais sobre o useEffect no tópico seguinte.

useEffect

O useEffect é um Hook que permite executar efeitos colaterais em seus componentes.

Alguns desses efeitos colaterais podem ser: busca de dados em uma API, atualizar diretamente o VirtualDOM e controlar temporizadores (setTimeout e setInterval).

O useEffect é utilizado para fazer o ciclo de vida de um componente em substituição às funções componentWillMount, componentDidMount, componentDidUpdate e componentWillUnmount.

As funções de ciclo de vida (componentWillMount, componentDidMount, componentDidUpdate e componentWillUnmount) não são mais utilizadas desde a atualização do React para a versão 16.8.

Sintaxe

Veja no Código 1 a sintaxe do hook useEffect.


  useEffect(<função>, <array de dependência>)
  
Código 1. Sintaxe do useEffect

Note que o useEffect recebe como primeiro parâmetro uma função que será executada assim que o componente for renderizado.

O segundo parâmetro recebido pelo useEffect será um array de dependência, podendo ser utilizado de forma opcional.

Com o array de dependência podemos controlar quando o useEffect executará a função recebida como parâmetro. Ou seja, caso o array seja alterado de alguma forma, o useEffect executará a função.

Agora entenda melhor como funcionam as fases do ciclo de vida de um componente. Para isso utilizaremos o useEffect no código de exemplo.

Inicialização

Esta é a primeira fase de um componente quando uma página é acessada, em que a aplicação insere seu State. Esse dado já fica acessível durante a renderização da página, como vemos no Código 2 e Figura 2.


  import { useState } from "react";
   
  export default function App() {
    const [contador, setContador] = useState(0);
   
    return (
      <div className="App">
        <h1>Contador: {contador}</h1>
        <button onClick={() => setContador(contador + 1)}>+</button>
      </div>
    );
  }
   
  
Código 2. Inicialização do ciclo de vida de um componente
Inicialização
Figura 2. Inicialização

Perceba que já temos o valor do state contador instanciado e visível em tela.

Montagem

Esta é a primeira fase do ciclo de vida de um componente. Aqui veremos que o useEffect é executado uma única vez quando o componente é montado, após a primeira renderização.

Esse recurso é normalmente utilizado para fazer requisições na API quando a página é recém carregada, como mostra o Código 3 e Figura 3.


  import { useState, useEffect } from "react";
   
  export default function App() {
    const [contador, setContador] = useState(0);
   
    useEffect(() => {
      console.log("executa o useEffect ao renderizar o componente");
    }, []);
   
    return (
      <div className="App">
        <h1>Contador: {contador}</h1>
        <button onClick={() => setContador(contador + 1)}>+</button>
      </div>
    );
  }
  
Código 3. Montagem do ciclo de vida de um componente
Montagem
Figura 3. Montagem

Perceba que aqui o useEffect será executado após a primeira renderização do componente.

Atualização

Esta é a terceira fase pela qual passa nosso componente. Após a fase de montagem onde o componente foi criado, a fase de atualização entra em cena. É aqui que quando o estado do componente muda ocorre a re-renderização, como vemos no Código 4 e Figuras 4 e 5.


  import { useState, useEffect } from "react";
   
  export default function App() {
    const [contador, setContador] = useState(0);
   
    useEffect(() => {
      console.log("executará o useEffect toda a vez que o [contador] mudar");
    }, [contador]);
   
    return (
      <div className="App">
        <h1>Contador: {contador}</h1>
        <button onClick={() => setContador(contador + 1)}>+</button>
      </div>
    );
  }
  
Código 4. Atualização do ciclo de vida de um componente
Atualização
Figura 4. Atualização
Atualização
Figura 5. Atualização

Perceba que a sintaxe aqui é similar da montagem, porém agora ao invés de um array vazio, colocaremos um array de dependência (contador) para que além da montagem do componente, a cada atualização do valor da dependência o useEffect chamará a função novamente e re-renderizá-las.

Desmontagem

Esta é a última fase do ciclo de vida de um componente e é responsável por fazer a limpeza do Virtual DOM. Quando precisamos desmontar um componente é ela que utilizaremos, como vemos no Código 5 e Figura 6.


  import { useState, useEffect } from "react";
   
  export default function App() {
    const [contador, setContador] = useState(0);
   
    useEffect(() => {
      return () => console.log("Aqui é quando o componente será desmontado!");
    }, []);
   
    return (
      <div className="App">
        <h1>Contador: {contador}</h1>
        <button onClick={() => setContador(contador + 1)}>+</button>
      </div>
    );
  }
  
Código 5. Desmontagem
Desmontagem
Figura 6. Desmontagem

Perceba na Figura 6 que quando passamos uma função para o return do useEffect, ele executa a função quando desmontar o componente.