React v16.3.0: Novos ciclos de vida e API de contexto

29 de março de 2018 por Brian Vaughn

Há alguns dias, escrevemos uma postagem sobre as próximas mudanças em nossos métodos de ciclo de vida legados, incluindo estratégias de migração gradual. No React 16.3.0, estamos adicionando alguns novos métodos de ciclo de vida para ajudar nessa migração. Também estamos introduzindo novas APIs para funcionalidades há tempo solicitadas: uma API de contexto oficial, uma API de referência de encaminhamento e uma API de referência de ergonomia.

Leia para saber mais sobre o lançamento.

API Oficial de Contexto

Por muitos anos, o React ofereceu uma API experimental para contexto. Embora fosse uma ferramenta poderosa, seu uso foi desencorajado por causa de problemas inerentes na API, e porque sempre pretendíamos substituir a API experimental por uma melhor.

A versão 16.3 introduz uma nova API de contexto que é mais eficiente e suporta tanto verificação de tipo estático quanto atualizações profundas.

Nota

A antiga API de contexto continuará funcionando para todas as versões do React 16.x, assim você terá tempo para migrar.

Aqui está um exemplo ilustrando como você pode introduzir um “tema” usando a nova API de contexto:

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

class ThemeProvider extends React.Component {
  state = {theme: 'light'};

  render() {
    return (
      <ThemeContext.Provider value={this.state.theme}>
        {this.props.children}
      </ThemeContext.Provider>
    );
  }
}

class ThemedButton extends React.Component {
  render() {
    return (
      <ThemeContext.Consumer>
        {theme => <Button theme={theme} />}
      </ThemeContext.Consumer>
    );
  }
}

Saiba mais sobre a nova API de contexto aqui.

API createRef

Anteriormente, o React fornecia duas maneiras de gerenciar refs: a legada API de string ref e a API de callback. Embora a API de string ref ter sido a mais conveniente das duas, ela tinha várias desvantagens e assim nossa recomendação oficial era usar a forma de callback.

A versão 16.3 adiciona uma nova opção para gerenciar refs que oferecem o conforto de uma string ref sem nenhuma das desvantagens:

class MyComponent extends React.Component {
  constructor(props) {
    super(props);

    this.inputRef = React.createRef();
  }

  render() {
    return <input type="text" ref={this.inputRef} />;
  }

  componentDidMount() {
    this.inputRef.current.focus();
  }
}

Nota:

As refs de callbacks continuarão sendo suportadas, além da nova API createRef.

Você não precisa substituir as callback refs em seus componentes. Elas são um pouco mais flexíveis, portanto, elas permanecerão como um recurso avançado.

Saiba mais sobre a nova API createRef aqui.

API forwardRef

Geralmente, os componentes React são declarativos, mas às vezes é necessário o acesso imperativo às instâncias do componente e aos nós DOM necessários. Isso é comum em casos de uso, como gerenciamento de foco, seleção ou animações. O React fornece refs uma maneira de resolver este problema. No entanto, o encapsulamento de componentes apresenta alguns desafios com as refs.

Por exemplo, se você trocar um <button> por um componente <FancyButton>, o atributo ref nele começará a apontar para o componente encapsulando em vez do nó DOM (e seria null para componentes funcionais). Embora isso seja desejável para componentes de “nível de aplicação” como FeedStory ou Comment que precisam ser encapsulados, isso pode ser incômodo para componentes “folha” como FancyButton ou MyTextInput que são tipicamente usados como seus equivalentes do DOM e podem precisar expor seus nós do DOM.

A referência de encaminhamento é um novo recurso de inclusão que permite que alguns componentes ref sejam recebidos, e passem para baixo (em outras palavras, “encaminhá-lo”) para um filho. No exemplo abaixo, FancyButton encaminha seu ref para um button do DOM que renderiza:

const FancyButton = React.forwardRef((props, ref) => (
  <button ref={ref} className="FancyButton">
    {props.children}
  </button>
));

// You can now get a ref directly to the DOM button:
const ref = React.createRef();
<FancyButton ref={ref}>Click me!</FancyButton>;

Dessa forma, os componentes que usam FancyButton podem obter uma ref ao nó inerente do button do DOM e acessá-lo se necessário for, como se usassem um button do DOM diretamente.

O encaminhamento de ref não está limitado para componentes de “folha” que rederizam nós do DOM. Se você escreve componente de alta-ordem, recomendamos o uso do encaminhamento de referência para passar automaticamente as ref para as instâncias do componente de classe wrapper.

Saiba mais sobre a API forwardRef aqui.

Mudanças no Ciclo de Vida do Componente

A API de componente de classe do React existe há anos com poucas mudanças. No entanto, como nós adicionamos suporte a recursos mais avançados (tal como limite de erros e o próximo modo de renderização assíncrona) nós estendemos esta API de maneiras que não foram originalmente projetadas.

Por exemplo, com a API atual, é muito fácil bloquear a renderização inicial com lógica não essencial. Em parte, isso ocorre porque há muitas maneiras de realizar uma determinada tarefa, e pode não ser claro qual é a melhor. Observamos que o comportamento de interrupção do tratamento de erros geralmente não é levado em consideração e pode resultar em vazamentos de memória (algo que também afetará o próximo modo de renderização assíncrona). A API do componente de classe atual também complica outros esforços, como o nosso trabalho em prototipar um compilador React.

Muitos desses problemas são exacerbados por um subconjunto dos ciclos de vida dos componentes (componentWillMount, componentWillReceiveProps, e componentWillUpdate). Esses também são os ciclos de vida que mais causam confusão na comunidade React. Por essas razões, vamos depreciar esses métodos em favor de alternativas melhores.

Reconhecemos que essa alteração afetará muitos componentes existentes. Por isso, o caminho de migração será o mais gradual possível e fornecerá alternativas de escape. (No Facebook, mantemos mais de 50.000 componentes React. Também dependemos de um ciclo de lançamento gradual!)

Nota:

Os avisos de deprecação serão ativados com uma versão 16.x futura, mas os ciclos de vida herdados continuarão funcionando até a versão 17.

Mesmo na versão 17, ainda será possível usá-los, mas eles terão um prefixo “UNSAFE_” para indicar que podem causar problemas. Nós também preparamos um script automatizado para renomeá-los no código existente.

Além de depreciar ciclos de vida inseguros, também estamos adicionando alguns novos ciclos de vida:

Saiba mais sobre essas mudanças no ciclo de vida aqui.

Componente StrictMode

StrictMode é uma ferramenta para destacar possíveis problemas em um aplicativo. Como o Fragment, oStrictMode não renderiza nenhuma UI visível. Ele ativa verificações e avisos adicionais para seus descendentes.

Nota:

StrictMode as verificações são executadas apenas no modo de desenvolvimento; eles não afetam a estrutura de produção.

Embora não seja possível para o “strict mode” detectar todos os problemas (por exemplo, certos tipos de mutação), ele pode ajudar em muitos. Se você ver avisos no “strict mode”, essas coisas provavelmente causarão bugs para renderização assíncrona.

Na versão 16.3, o StrictMode ajuda:

  • Identificando componentes com ciclos de vida inseguros
  • Aviso sobre o uso de string legada da API ref
  • Detectando efeitos colaterais inesperados

Funcionalidades adicionais serão adicionadas com versões futuras do React.

Aprenda mais sobre o componente StrictMode aqui.