Context API do React 16.3.0 e métodos de ciclo de vida

React 17 de Abr de 2018

O ReactJS v16.3.0 está repleto de novidades para os desenvolvedores e a feature mais comentada recentemente é a nova Context API que foi acusada como substituta do Redux, mas será que seria esse o fim da arquitetura Flux? Calma lá jovem…

Além da nova context API, a recente versão do ReactJS também trouxe alguns novos métodos de ciclo de vida aos componentes e, além disso, vale lembrar que dois métodos estão deixando de existir.

Se você ainda não conhece o ReactJS recomendo muito essa série aqui no blog para você ter os primeiros conhecimentos dessa ferramenta.

Chega de falar e bora entender como isso funciona no código!

Nova context API

Desde os primórdios do ReactJS, sempre existiu uma Context API, o problema é que a mesma era muito instável e com diversos problemas relacionados à performance. Mas pera, por que precisamos do contexto?

Se você já criou alguns projetos utilizando o modelo de componentização sabe que para compartilhar informações entre componentes totalmente desconexos você vai ter que fazer alguma gambiarra ou utilizar a famosa arquitetura flux com Redux.

Com a nova Context API conseguimos facilmente repassar informações de qualquer tipo entre diversos componentes do React.

Imagine que precisamos repassar uma informação do tema ativo (claro ou escuro) para estilizar alguns componentes em nossa aplicação:

Começamos criando uma variável de contexto com o comando React.createContext passando como parâmetro o valor padrão quando nenhum valor existir nessa variável.

import React, { Component } from 'react';

const ThemeContext = React.createContext('claro');

Pronto! Nossa variável ThemeContext já pode ser considerada uma variável de contexto, mas como fazemos para mudar seu valor? Precisamos utilizar um componente chamado Provider que pertence à essa variável:

import React, { Component } from 'react';

const ThemeContext = React.createContext('light');

class App extends Component {
  state = {
    theme: 'light',
  };

  changeTheme = () => {
    this.setState({ 
      theme: this.state.theme === 'light' 
        ? 'dark' 
        : 'light'
    });
  }

  render() {
    return (
      <ThemeContext.Provider value={this.state.theme}>
        <button onClick={this.changeTheme}>Alterar tema</button>
        <ThemedButton />
      </ThemeContext.Provider>
    );
  }
}

No exemplo acima, criamos um ThemeContext.Provider com uma única propriedade chamada value que é responsável por prover o valor da variável de contexto. Essa variável pode ser qualquer coisa e por isso estamos utilizando uma propriedade do estado chamada theme para compôr-la.

Também criei um método changeTheme que altera o tema de light para dark e vice-versa para garantir que o valor está sendo repassado.

Ótimo, agora que já provemos o valor da nossa variável de contexto, nós podemos consumi-la em qualquer lugar da aplicação que estiver entre a tag Provider:

function ThemedButton(props) {
  return (
    <ThemeContext.Consumer>
      {theme => (
        <a style={{ backgroundColor: theme === 'dark' ? '#333' : '#CCC' }}>
          Meu botão
        </a>
      )}
    </ThemeContext.Consumer>
  );
}

Com o ThemeContext.Consumer agora temos acesso ao valor da variável de contexto mas perceba que não exibimos ela simplesmente em tela, precisamos utilizar uma função dentro do Consumer que recebe como parâmetro o valor da variável e retorna um elemento.

Com esse exemplo acima temos o seguinte resultado:

Veja que em nenhum momento precisamos repassar ao componente ThemedButton uma propriedade com o tema, nossa variável de contexto fez isso para nós e esse valor pode ser consumido em qualquer local da aplicação que estiver dentro do Provider.

Legal né, mas isso vai acabar com o Redux? Na verdade não.

O que vai acontecer daqui pra frente é que você não vai mais precisar utilizar o Redux sempre que precisar compartilhar informações entre componentes, mas vale lembrar que a arquitetura Flux é muito mais do que simplesmente compartilhamento de dados, tem a ver com estrutura, com fluxo de informações e arquitetura dos dados da aplicação.

Por isso, não deixe de estudar Redux, mas entenda que a API de contexto pode sim suprimir sua utilidade em funcionalidades isoladas e principalmente em projetos menores.

Novos métodos de ciclo de vida

Se você já estudou o ciclo de vida dos componentes ReactJS sabe que existem muitos métodos para controlarmos o fluxo de mount/atualização/unmount de cada elemento na tela.

Antes de vermos os novos módulos, vale deixar claro que o ReactJS está depreciando três métodos: componentWillMount, componentWillReceiveProps, e componentWillUpdate.

Apesar de termos três estágios do ciclo de vida a menos agora, nessa versão do React 16.3.0 foram adicionados dois novos métodos:

  • getDerivedStateFromProps – Utilize esse método quando você precisar setar o state do seu componente baseado em alguma propriedade que ele está recebendo. Esse ciclo de vida é executado tanto na inicialização do componente quanto na sua atualização de propriedades e deve retornar as alterações no estado do componente baseada nas propriedades ou nulo.
  • getSnapshotBeforeUpdate – Um novo ciclo utilizado para você buscar informações da DOM antes das alterações ocorrerem. Um exemplo é uma lista grande, ao atualizar seus itens seria interessante saber aonde estava o scroll do usuário para mantê-lo ou até reposiciona-lo. Todo valor retornado por esse método é enviado ao componentDidUpdate que é o ciclo executado na sequência.

Concluindo

Agora que você já conhece a nova API de contexto do React já sabe que a arquitetura Flux e o Redux não vão morrer, na verdade isso vai ajudar muito em projetos que você não precisa de toda a complexidade de um gerenciamento de estado mais complexo como o Redux e precisa apenas compartilhar algumas informações entre componentes.

Com as alterações nos métodos de ciclo de vida, fique ligado para remover os métodos depreciados e trabalhar com os novos métodos, principalmente o getDerivedStateFromProps que ajuda muito a controlarmos o estado que depende de alguma propriedade do componente.

É isso aí, deixa um comentário aí em baixo contando o que achou dessa nova API de contexto e se você acha que o Redux irá acabar 🙂

Marcadores

Diego Fernandes

Programador full-stack, apaixonado pelas melhores tecnologias de desenvolvimento back-end, front-end e mobile, é co-fundador e CTO na Rocketseat.