Uma foto minha vestido com o uniforme da Grifinória do Harry Potter

Willian JustenSoftware Engineer

Instrutor na Udemy, escrevo sobre o mundo front end, viagens, vida pessoal e mais.

← Voltar na listagem

Novidades do React 16

Veja o que tem de novo com o novo lançamento do React.

Introdução

Fala pessoal, o post de hoje vai ser bem rapidinho para atualizar a galera sobre as coisas novas do React 16 e mais umas coisinhas que aconteceram no ecosistema React. Como vocês já devem saber, eu gosto bastante de React e já faz um bom tempo que escrevo uma coisa ou outra. Mas seguramente essa versão foi a que teve mais impacto de todas e vou separar esses detalhes logo mais.

Enquanto escrevo esse post, vou ouvindo o novo album do Foo Fighters chamado Concrete and Gold que ficou demais!

Confusão, reclamações e mais sobre a licença do React

Se você esteve um pouco desligado nos últimos tempos, estava rolando uma treta sobre a licença que o Facebook usava no React e com isso vieram vários posts falando para as pessoas pararem de usar o React em suas aplicações. Um dos mais famosos era o If you’re a startup, you should not use React, que só com esse título causou uma confusão generalizada...

Sendo sincero, eu devo ter recebido um monte de emails e mensagens perguntando se então não valia mais a pena estudar React, já que o Facebook ia "roubar" tudo e afins. Muito disso por causa desses posts de títulos bem clickbaits e complicados. O Facebook escreveu até um post sobre a escolha da licença e como funciona. Mas isso não colou e muiiiita gente continuou a reclamar sobre a licença.

E bom, o Facebook ouviu a comunidade e resolveu mudar a licença do React e outras bibliotecas para a licença do MIT.

Então, resumindo, o React continua sendo uma ótima biblioteca para trabalhar e vale muito a pena estudar sim tá! =D

A completa reescrita do React

O React vai ser todo reescrito? Ferrou, vou ter que aprender tudo de novo? Tá parecendo Angular isso aí!

Sim, um monte de gente estava com esse discurso quando soube da reescrita. Só que o que eles não imaginavam que essa reescrita seria interna e não iria afetar a API publica do React, ou seja, melhor performance, menor tamanho, mas com os métodos e coisas que usávamos antes!

Essa reescrita recebeu o nome de Fiber e você pode saber mais sobre ela nesse documento do github ou então nessa palestra da Lin Clark. E também esse post hiper atualizado falando um pouco de como foi o processo de desenvolvimento dessa reescrita, sempre objetivando não quebrar o que já existia.

O Fiber é responsável pela maioria das novas features do React 16 como error boundaries e fragments. Eles também já estão trabalhando com async rendering, que você pode ter um preview de como funciona, logo abaixo:

Novas features / Mudanças

Seguem então alguns dos detalhes legais dessa nova versão:

Tamanho reduzido

Apesar de várias adições legais, o React ficou menor! Claro que não se compara com outras bibliotecas extremamente pequenas como o Preact, mas já é um grande avanço. Os tamanhos ficam então:

  • react agora 5.3 kb (2.2 kb gzipped), antes 20.7 kb (6.9 kb gzipped).
  • react-dom agora 103.7 kb (32.6 kb gzipped), antes 141 kb (42.9 kb gzipped).
  • react + react-dom agora 109 kb (34.8 kb gzipped), antes 161.7 kb (49.8 kb gzipped).

Ou seja, a diminuição foi de cerca de 30%, isso é muito importante para evitar criar apps gigantescas que demoram muito para carregar. Essa diminuição de tamanho muito ocorreu por causa do uso do Rollup, que melhorou o empacotamento da biblioteca.

Fragments e Strings

Agora você pode retornar um array de elementos diretamente para o render. Antes precisávamos encapsular os elementos em alguma <div> ou outro elemento. Agora não é mais necessário isso =)

// antes encapsulando com uma div
render() {
  return (
    <div>
      <h1>Meu Título</h1>
      <p>Meu texto lindo aqui.</p>
    </div>
  )
}

// agora usando como array
render() {
  return [
    <h1 key='header'>Meu Título</h1>,
    <p key='text'>Meu texto lindo aqui.</p>
  ]
}

Lembrando de não esquecer de usar o key para não receber nenhum warning. No futuro eles planejam fazer uma forma para também não precisar de adicionar o key para esses casos. E o mesmo ocorre para strings, que agora são suportadas diretamente:

// antes encapsulando com um span
render() {
  return <span>Usando o Span!<span>;
}

// agora usando como string direta
render() {
  return 'Sem Spans!';
}

Melhor error handling

Antes, quando tínhamos algum erro no React, podia acabar prejudicando tanto a renderização da tela atual, como o funcionamento das outras coisas a serem feitas depois. Para evitar esse tipo de erro tão grave, a galera do React pensou que "Uma parte da UI não precisa quebrar o aplicativo todo".

Com o Error boundaries nós podemos capturar esses errors em qualquer parte do componente, jogar no console o erro e mostrar um fallback na UI, com uma mensagem mais informativa, por exemplo.

E como isso funciona? É bastante simples! Temos um novo método chamado componentDidCatch, que vai ser responsável por fazer o report desse erro para nós e então facilitar para tratarmos. Segue um exemplo básico abaixo:

componentDidCatch(error, info) {
  // Adicionamos uma variável no nosso state
  // para tratarmos na nossa UI
  this.setState({ ...state, hasError: true });
  // E você também tem 2 paramêtros para reportar
  console.log(error); // o erro em si
  console.log(info); // contém o Component Stack
}

Depois de definido o nosso componentDidCatch podemos ir no método render do nosso componente e só colocar a validação necessária, para imprimir o componente que queremos ou caso tenha um erro, imprimir nossa mensagem, por exemplo:

 render() {
    if (this.state.hasError) {
      // Imprimindo uma mensagem de erro
      return <h1>Ixi, alguma coisa deu errado =(</h1>;
    }
    else {
      // retornando o componente de fato
      ...
    }
  }

Portals

Essa feature permite renderizar um elemento filho num DOM node que existe fora da hierarquia do pai do componente. Como assim? Em geral, quando retornamos um elemento de método render de um componente, ele é montado no DOM com filho do nó pai mais próximo. Exemplo:

render() {
  // React monta uma nova div e renderiza o filho dentro
  return (
    <div>
      {this.props.children}
    </div>
  );
}

Mas, as vezes é interessante inserirmos o filho numa posição diferente do DOM:

render() {
  // O React não vai criar uma nova div. Ele vai renderizar o filho dentro do `domNode`.
  // `domNode` é qualquer nó válido, independente de sua localização no DOM.
  return ReactDOM.createPortal(
    this.props.children,
    domNode,
  );
}

Um caso típico do uso de portals é quando um componente pai tem overflow: hidden ou z-index, mas você precisa que o filho "vaze" do container. Como, por exemplo, tooltips, hovercards e dialogs.

Você pode ler mais sobre nesse post do Facebook.

Melhor server-side rendering

Graças ao Fiber novamente, toda a forma de server-side rendering foi reescrita e agora está extremamente rápida! Suporta streaming e com isso você pode enviar os dados para o client de forma melhor e mais ágil. E graças a nova forma de empacotamento, que não necessita mais do process.env, o processo ficou bem mais rápido.

Tem um post bem bacana falando bastante sobre isso, indicando que o React 16 acaba sendo 3x mais rápido que o React 15.

Você pode ler mais sobre o ReactDomServer está funcionando, nesse post.

Suporte a DOM Attributes

Antes não era possível criar atributos customizados na nossa tag. Ou seja, se não fosse camelCase ou tivesse data- ou aria-, o React acabava não imprimindo o que queríamos.

<div mycustomattribute="something" />

// React 15 iria imprimir
<div />

// React 16 imprime o que desejo
<div mycustomattribute="something" />

Essa é uma mudança pequena, mas que pode ser útil para aqueles casos onde necessitamos de atributo para um browser específico ou alguma coisa de API externa. Você pode ler mais sobre essa feature aqui.

Sobre atualização, breaking changes, deprecations...

O primeiro aviso é: Se você já tem sua aplicação rodando no React 15.6 sem nenhum warning, irá funcionar no React 16.

Deprecations

Para hidratar um container server-side agora tem uma API explicita nova. Agora você pode usar ReactDOM.hydrate ao invés de ReactDOM.render. Continue usando ReactDOM.render se estiver fazendo só client-side rendering.

O suporte ao React Addons foi descontinuado e com exceção do react-addons-perf que terá uma versão nova, os outros addons não terão atualizações.

No momento o react-addons-perf não funciona no React 16 e enquanto isso, é encorajado usar as ferramentas do Browser para medir performance.

Breaking Changes

Como o objetivo foi não impactar fortemente o ecosistema já existente, as breaking changes são bem pequenas e que só afetam casos bem incomuns.

  • React 15 tinha um suporte (sem documentação e bem limitado) para Error Boundaries que era o unstable_handleError. Esse método foi renomeado para componentDidCatch.
  • ReactDOM.render e ReactDOM.unstable_renderIntoCotnainer agoram retornam null se chamados dentro de um método de lifecycle. Para trabalhar com isso, você pode usar portals ou refs.
  • setState:
    • Chamar setState com null não ativa uma atualização dos estados. Isso permite que você defina uma função para atualizar caso queira renderizar novamente.
    • Chamar setState diretamente num render vai causar uma atualização dos estados. Lembrando que você não deveria chamar setState dentro de um render.
    • Os callbacks de setState agora ativam imediatamente depois do componentDidMount/componentDidUpdate ao invés de após todos os componentes serem renderizados.
  • Ao trocar <A /> por <B />, B.componentWillMount agora vai sempre acontecer antes de A.componentWillUnmount. Antes, A.componentWillUnmount podia inicializar primeiro em certos casos.
  • Antes, mudar o ref de um component sempre iria desmontar a ref antes que o render do componente fosse chamado. Agora, o ref é mudado depois, quando aplicadas as mudanças no DOM.
  • componentDidUpdate lifecycle não recebe mais o parâmetro prevContex.
  • Shallow Renderer não chama mais o componentDidUpdate porque as refs do DOM não estão disponíveis. Isso faz ser consistente com o componentDidMount que não era chamado nas versões anteriores também.

Empacotamento

Como dito antes, a forma de empacotamento do React mudou. E não existe mais react/lib/* e react-dom/lib/*. E os nomes/caminhos mudaram para enfatizar a diferença entre os builds de produção e desenvolvimento:

  • react/dist/react.jsreact/umd/react.development.js
  • react/dist/react.min.jsreact/umd/react.production.min.js
  • react-dom/dist/react-dom.jsreact-dom/umd/react-dom.development.js
  • react-dom/dist/react-dom.min.jsreact-dom/umd/react-dom.production.min.js

Requisitos

O React 16 depende dos collection types Map e Set. Se você precisa dar suporte para browsers antigos que não suportam nativamente, será necessário incluir um polyfill na aplicação. Você pode ver mais sobre aqui.

Site atualizado da Documentação

É isso mesmo, refizeram o site da documentação, ficou mais limpo, mais fácil de acessar os menus e numa linguagem de bem fácil entendimento, dá uma checada lá.

Conclusão

Bom galera, é basicamente isso. O React continua firme e forte e cada vez melhorando mais! Não precisa ter medo de começar a estudar não, porque a biblioteca vai longe ainda. E essas mudanças novas foram mais do que bem vindas!