Passado e futuro?
Tags: react, javascript, components, lifecycle
Published: 2021-03-25 21:05:09

<h4>
Olá! 
</h4>
<p>
Se você chegou direto aqui e não tem base nenhuma sobre Reat, aconselho a voltar e ler o <a href="https://dev.to/thiagopederzolli/react-e-seus-tres-mosqueteiros-4lh">React e seus três mosqueteiros</a> primeiro para se contextualizar melhor. 
</p>
<p>
Agora se você já é familiarizado com os conceitos de componentes, propriedades e estados em React, boa leitura!💜
</p>
```bash
-------------------------------------------------------------
```
<p>
Dando continuidade aos textos sobre conceitos básicos de React, temos a questão de criação de componentes. A forma de como os componentes são criados em React dividem-se em duas fases, o início e evolução da ferramenta através do <strong>Class Component</strong>, até o momento que foi implementado os <strong><em>Hooks</em></strong> no React que tornaram viáveis utilizar algumas funcionalidades essenciais do React com <strong>Functional Components</strong>.
</p>
<p>
De sua origem até o surgimento dos Hooks, os estados só eram acessíveis através de Class Components. E essa implementação dos Hooks é algo recente,não vá lendo isso e achando que <em>“ah, então agora só estudar Functional Components que ta tranquilo.”</em>. Você irá quebrar a cara em diversas oportunidades de inserção no mercado.
</p>
<p>
Talvez não tenha mais tanto sentido na criação de Class Components, porém você ainda pode lidar com diversos códigos legados e outras ferramentas que criam a base dos componentes em forma de Class.
</p>
<h2>
Imutabilidade:
</h2>
<p>
Um detalhe importante de lembrar antes de entrar na diferenciação de como os componentes funcionam, é a questão da imutabilidade do React.
</p>
<p>
Por que é importante lembrar disso agora? Porque nos exemplos falarei sobre os estados e esse conceito é muito importante para entender a atualização de estados.
</p>
<p>
O que esse conceito em poucas palavras é a ideia de que <strong>um valor de uma variável nunca deve ser alterada diretamente</strong>, precisamos recuperar esse valor, alterá-lo em uma nova variável juntando o novo valor e então atribuir essa variável ao método de atualizar o estado, garantindo assim um <em>novo espaço de memória</em> com essa nova informação, sem afetar diretamente aquela informação anterior que já ocupava outro espaço na memória.
</p>
<h2>
Class Components:
</h2>
<p>
Baseado na premissa de Objects do React, o Class é um objeto que estende o objeto Component, um objeto nativo do React responsável por ter as principais propriedades e métodos para criação de componentes, por isso começamos ele com a seguinte sintaxe:
</p>
```jsx
import React, { Component } from 'react';

class ExampleComponent extends Component {
  render() {
    return (
      <h1>Olá Mundo!</h1>
    )
  }
}

export default ExampleComponent;
```
<p>
Um dos principais métodos que ele herda é o <strong>render()</strong>, responsável por retornar o JSX daquele componente. Porém podemos criar novos métodos para utilizar neste componente. Porém, por padrão, os métodos criados não são vinculados a classe, para isso, precisamos invocar outro método herdado que é o <strong>constructor()</strong>, ele nos permitirá fazer o <strong>bind()</strong> do método criado com a instância, que é representada pelo termo <strong><em>this</em></strong>, quando você faz o bind do método com o <em>this</em>, você está <strong>vinculando aquele método à instância do componente associado com o elemento da DOM que representa esse componente</strong>.
</p>
<p>
Se você criar um método e usar diretamente no render, ele será executado, porém se ele não for de uso imediato, como um método que irá fazer uma atualização de estado, precisamos garantir o bind, para isso precisamos do método constructor() e dentro dele do método <strong>super()</strong>. Dentro do constructor(), primeiro declaramos o super() que irá garantir que nosso componente continuará herdando os métodos do Component e também será possível adicionar novos métodos.
</p>
<p>
Feito isso podemos fazer o bind() de nossa função e teremos algo assim:
</p>
```jsx
import React, { Component } from 'react';

class ExampleComponent extends Component {
  constructor() {
    super();
    this.handleChange = this.handleChange.bind(this);
  }

  handleChange() {
    console.log('atualiza um estado!');
  }
  
  render() {
    return (
      <h1>Olá Mundo!</h1>
    )
  }
}

export default ExampleComponent;
```
<p>
Lembrando que precisamos colocar o <em>this</em> antes do nome da função também para vincular ao método da nossa instância.
</p>
Sobre as props, o acesso é da mesma forma que se acessa os estados, através do <em>this</em> para vincular a instância atual, caso precise usar uma props para atualizar algum valor de estado inicial na hora de criar o state do componente, lembre-se passar as props por parâmetro para o constructor(props) e super(props):
</p>
```jsx
import React, { Component } from 'react';

class ExampleComponent extends Component {
  constructor(props) {
    super(props);
    
    this.state = {
      newState: this.props.data
    }
  }
  
  render() {
    return (
      <h1>Olá Mundo!</h1>
    )
  }
}

export default ExampleComponent;
```
<p>
Por fim, outra questão muito importante do método constructor() é que é nele que conseguimos construir nossos estados dentro de um Class Component. A criação de estados é bem diferente de uma forma de criação de componente, no caso de Class Components, construimos dentro do constructor e sua atualização se dá pelo mesmo método, vou mostrar o exemplo clássico do contador com Class Component e Functional Component para que seja possível compreender como criar e atualizar o estado.
</p>
<p>
Em um Class Component teríamos um código assim:
</p>
```jsx
import React, { Component } from 'react';

class Counter extends Component {
  constructor() {
    super();
    this.state = {
      count: 0
    }
    this.increment = this.increment.bind(this);
  }

  increment() {
    this.setState({
      count: this.state.count + 1,
    })
  }
  
  render() {
    return (
      <div>
        <h1>{count}</h1>
        <button
          type="button"
          onClick={this.increment}
        >
          Aumentar em 1
        </button>
      </div>
    );
  }
}

export default Counter;
```
<p>
Outro detalhe relevante da criação de componentes, ai tanto para Class quanto Functional é no return, que o <strong>JSX só permite o retorno de um elemento HTML por componente</strong>. Isso <strong>não</strong> quer dizer que você, <em>literalmente</em>, só pode retornar um elemento HTML por componente, mas o retorno final deve estar englobado dentro de um elemento só, por isso vocês podem perceber que o retorno do contador tem uma tag <h1/> e uma tag <button/>, mas ambas estão englobadas por uma tag <div/>.
</p>
<p>
Outra questão relevante sobre os componentes é que eles possuem <strong>ciclos de vida</strong>, que era de domínio do Class Component e foi permitido ao Functional Component repetir os comportamentos com a implementação de Hooks.
</p>
<p>
Os ciclos de vida referem-se aos momentos de renderização do componente e os métodos para trabalhar esses momentos acredito que são auto-explicativos. Sobre a implementação deles em código acredito que cabe um texto a parte para explicações, mas os principais são:
</p>
<ul>
<li>
<strong>componentDidMount</strong> para executar uma ação após o componente ser inserido no DOM;
</li>
<li>
<strong>shouldComponentUpdate</strong> para avaliar se uma atualização do componente deve ou não acontecer naquele momento;
</li>
<li>
<strong>componentDidUpdate</strong> para executar uma ação após o componente ser atualizado;
</li>
<li>
<strong>componentWillUnmount</strong> para realizar uma ação antes de o componente ser desmontado.
</li>
<h2>
Functional Components:
</h2>
<p>
Componentes funcionais cresceram em termos de utilização após o lançamento dos Hooks, que permitem uso de estados e ciclos de vida. A sintaxe também acaba sendo mais simples, acabam-se as preocupações de bind, pois acaba a questão da herança de objetos, agora trabalhamos com funções, então a base do componente acaba sendo simples:
</p>
```jsx
import React from 'react';

function ExampleComponent() {
  return (
    <h1>Olá Mundo</h1>
  )
}

export default ExampleComponent;
```
<p>
A partir dai podemos trabalhar com os estados a partir de um hook específico para isso que é o <strong>useState()</strong>. Focando no que é importante para nós, vamos nos atentar ao fato de o useState ser um método que irá, principalmente, <em>retornar um array, que o que nos importa são os dois primeiros elementos desse array</em>.
</p>
<p>
O primeiro elemento do nosso array será a variável que irá armazenar o valor do nosso estado inicial e quando ele for atualizado. O segundo elemento será o método responsável por atualizar o valor desse estado. <em>Por convenção, os nomes desses elementos são, para o primeiro, o nome do estado que é algo relacionado ao dado que irá armazenar e, para o segundo, o prefixo set seguido do nome do estado</em>. FIcará mais compreensível no exemplo abaixo.
</p>
<p>
Perceba que, diferentemente do Class Component, onde todos estados ficavam dentro do objeto <strong>this.state</strong> e tudo era atualizado pelo <strong>this.setState()</strong>, no Functional Component, <em>cada estado possui uma variável própria e terá seu método para ser atualizado</em>:
</p>
```jsx
import React, { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0);

  const increment = () => {
    setCount(count + 1);
  }

  return (
    <div>
      <h1>{count}</h1>
      <button
        type="button"
        onClick={increment}
      >
        Aumentar em 1
      </button>
    </div>
  );
}

export default Counter;
```
<p>
Perceba, também, que é passado como argumento para o useState o valor inicial da variável count.
</p>
<p>
Sobre os ciclos de vida com o Functional Component, temos outro Hook, que é <strong>useEffect()</strong>, ele também é um método que recebe dois argumentos, <em>o primeiro é a função que deve ser executada e o segundo é um array de dependências</em>. 
</p>
<p>
Dependências essas que definirão o ciclo de funcionamento do useEffect(), por exemplo, se passarmos o array vazio, ele funcionará como o componentDidMount, executando a função passada para ele apenas uma vez. Isso é ótimo para momentos que trabalhamos com requisições API para atualizar dados do nosso componente.
</p>
<p>
Trago aqui parte do código do primeiro módulo do Ignite, trilha React, da Rocketseat como um breve exemplo de como funcionaria essa questão de utilizar o useEffect() com um ciclo de vida similar ao componentDidMount para atualizar um estado com o retorno de uma requisição API.
</p>
```jsx
import React, { useEffect, useState } from "react";

function RepositoryList() {
  const [repositories, setRepositories] = useState([]);

  useEffect(() => {
    fetch('https://api.github.com/orgs/rocketseat/repos')
      .then(response => response.json())
      .then(data => setRepositories(data));
  }, []);

  return (
    <section>
      <h1>Repositórios</h1>
    </section>
  )
}

export default RepositoryList;
```
<p>
Esse código está incompleto em termos de funcionamento, porque precisaria explicar outros conceitos e já me alonguei nas explicações deste texto. Mas o foco dele é a sintaxe para entender o uso do useEffect().
</p>
<p>
Se você já estudou sobre promises, async/await, você pode estar se perguntando porque o uso do .then() ao invés de o async/await. O useEffect <strong><em>não aceita diretamente uma função assíncrona</em></strong>, então se você optar por trabalhar com async/await, seria necessário fazer uma função anônima que terá em seu corpo a função assíncrona que fará a requisição, tendo algo similar a:
</p>
```jsx
import React, { useEffect, useState } from "react";

function RepositoryList() {
  const [repositories, setRepositories] = useState([]);

  useEffect(() => {
    const fetchRepos = async() => {
      const response = await fetch(`
         https://api.github.com/orgs/rocketseat/repos`);
      const data = await response.json();
      setRepositories(data);
    }

    fetchRepos();
  }, []);

  return (
    <section>
      <h1>Repositórios</h1>
    </section>
  )
}

export default RepositoryList;
```
<p>
E, ao meu ver, essas são as principais diferenças entre os métodos de criação de um componente que eu me deparei até o momento. Concorda? Acredita que há mais alguma diferença relevante? Me equivoquei em alguma informação? Por favor, não hesite em colaborar com qualquer informação, meu foco é contribuir com a comunidade, mas principalmente encontrar uma forma de documentar meu aprendizado e levar minhas compreensões ao maior alcance possível, para que possamos reforçar os entendimentos corretos e reparar entendimentos errôneos.
</p>