React v16.0

26 de setembro de 2017 por Andrew Clark

Estamos felizes em anunciar o lançamento do React v16.0! Entre as mudanças estão algumas solicitações antigas de recursos, incluindo fragmentos, error boundaries, portais, suporte para atributos DOM customizados, aprimoramento na renderização de servidor e tamanho de arquivo reduzido.

Novos tipos de retorno na renderização: fragmentos e strings

Agora você pode retornar um array de elementos no método render de um componente. Assim como outros arrays, você precisará adicionar uma prop key para cada elemento para evitar um warning:

render() {
  // Não é mais necessário envolver os itens da lista em um elemento extra!
  return [
    // Não esqueça das keys :)
    <li key="A">First item</li>,
    <li key="B">Second item</li>,
    <li key="C">Third item</li>,
  ];
}

A partir do React 16.2.0, foi adicionado ao JSX suporte a uma sintaxe especial de fragmento que não exige keys.

Adicionamos suporte para retornar strings também:

render() {
  return 'Look ma, no spans!';
}

Veja a lista completa de tipos de retornos.

Gerenciamento de erros aprimorado

Anteriormente, erros de tempo de execução durante a renderização podiam colocar o React em um estado quebrado, produzindo mensagens de erro enigmáticas e exigindo uma atualização da página para recuperar. Para resolver esse problema, o React 16 usa uma estratégia de tratamento de erros mais resiliente. Por padrão, se um erro for lançado dentro dos métodos de renderização ou ciclo de vida de um componente, toda a árvore de componentes será desmontada da raiz. Isso impede a exibição de dados corrompidos. No entanto, provavelmente não é a experiência ideal para o usuário.

Ao invés de desmontar a aplicação inteira toda vez que houver um erro, você pode usar error boundaries. Error Boundaries são componentes especiais que capturam erros dentro de sua subárvore e exibem uma UI de fallback em seu lugar. Pense que Error Boundaries são como instruções try-catch, mas para componentes React.

Para mais detalhes, veja nossa publicação anterior sobre gerenciamento de erros no React 16.

Portais

Portais fornecem uma maneira de primeira classe para renderizar componentes filhos em um nó do DOM que existe fora da hierarquia DOM do componente pai.

render() {
  // React *não* criará uma nova div. Irá renderizar os filhos dentro de `domNode`.
  // `domNode` é qualquer nó DOM válido, independentemente de sua localização no DOM.
  return ReactDOM.createPortal(
    this.props.children,
    domNode,
  );
}

Veja um exemplo completo na documentação para portais.

Renderização de servidor aprimorada

Foi incluída no React 16 uma reescrita completa na renderização de servidor. É muito rápida. Suporta streaming, para que você possa enviar bytes para o cliente mais rapidamente. E graças a uma nova estratégia de empacotamento, que compila as verificações do process.env (acredite ou não, ler process.env no Node é muito lento!), você não precisa mais empacotar o React para ter boa performance em renderização de servidor.

Sasha Aickin, membro do Core Team escreveu um ótimo artigo descrevendo as melhorias de SSR no React 16. De acordo com os benchmarks feitos por Sasha, renderização de servidor no React 16 é aproximadamente três vezes mais rápido que no React 15. “Quando comparado ao React 15 com process.env compilado, há um ganho de 2.4x no Node 4, em torno de 3x de ganho de desempenho no Node 6, e uma completa melhoria de 3.8x no recém lançado Node 8.4. E se você comparar com o React 15 sem compilação, o React 16 tem um ganho de uma ordem de magnitude completa em SSR na versão mais recente do Node!” (Como destaca Sasha, lembre-se de que esses números são baseados em parâmetros de referência sintéticos e podem não refletir o desempenho do mundo real.)

Além disso, o React 16 é melhor para hidratar o HTML renderizado pelo servidor, assim que é entregue ao cliente. Não é mais necessário que a renderização inicial corresponda exatamente ao resultado do servidor. Em vez disso, tentará reutilizar o máximo possível do DOM existente. Chega de checksums! Em geral, não recomendamos que você processe conteúdo diferente no cliente e no servidor, mas ele pode ser útil em alguns casos (por exemplo, registros de data e hora). No entanto, é perigoso ter nós ausentes na renderização do servidor, pois isso pode causar a criação de nós irmãos com atributos incorretos.

Veja a documentação do ReactDOMServer para mais detalhes.

Suporte para atributos DOM customizados

Ao invés de ignorar atributos HTML e SVG não reconhecidos, o React agora os passará para o DOM. Isso nos traz o benefício adicional de nos livrar da maioria da lista de permissões de atributos do React, resultando em tamanhos de arquivo reduzidos.

Tamanho de arquivo reduzido

Apesar de todas essas adições, o React 16 é realmente menor em comparação com 15.6.1!

  • react agora é 5.3 kb (2.2 kb com gzip), antes era 20.7 kb (6.9 kb com gzip).
  • react-dom agora é 103.7 kb (32.6 kb com gzip), antes era 141 kb (42.9 kb com gzip).
  • react + react-dom agora são 109 kb (34.8 kb com gzip), antes eram 161.7 kb (49.8 kb com gzip).

Isso equivale a uma redução do tamanho de 32% combinados em comparação com a versão anterior (30% após o gzip).

A diferença de tamanho é parcialmente atribuída a uma alteração no empacotamento. O React agora usa o Rollup para criar flat bundles para cada um de seus diferentes formatos de destino, resultando em ganhos tanto de tamanho como tempo de execução. O formato de flat bundle também significa que o impacto do React no tamanho do pacote é praticamente consistente, independentemente de como você disponibiliza seu aplicativo, seja com Webpack, Browserify, pacotes configuráveis UMD pré-criados ou qualquer outro sistema.

Licença MIT

Caso você tenha perdido, React 16 está disponível sob a licença MIT. Nós também publicamos o React 15.6.2 sob a licença MIT, para aqueles que não podem atualizar imediatamente.

Nova arquitetura principal

O React 16 é a primeira versão do React construída sobre uma nova arquitetura principal, codinome “Fiber”. Você pode ler tudo sobre esse projeto no blog de engenharia do Facebook. (Spoiler: reescrevemos React!)

Fiber é responsável pela maior parte das novas funcionalidades no React 16, como error boundaries e fragmentos. Nos próximos lançamentos, vocês podem esperar por novas funcionalidades quando começarmos a desbloquear todo o potencial do React.

Talvez a área mais empolgante na qual estamos trabalhando seja a renderização assíncrona- uma estratégia para agendar cooperativamente o trabalho de renderização, liberando periodicamente a execução do navegador. O resultado é que, com a renderização assíncrona, os aplicativos serão mais responsivos porque o React evitará o bloqueio da main thread.

Esta demonstração fornece uma prévia dos tipos de problemas que a renderização assíncrona pode resolver:

Dica: Preste atenção no quadrado preto girando.

Acreditamos que a renderização assíncrona é importante e representa o futuro do React. Para tornar a migração para a v16.0 o mais suave possível, ainda não estamos habilitando nenhum recurso assíncrono, mas estamos animados em começar a liberá-los nos próximos meses. Fique ligado!

Instalação

React v16.0.0 está disponível no registro do npm.

Para instalar o React 16 com Yarn, execute:

yarn add react@^16.0.0 react-dom@^16.0.0

Para instalar o React 16 com npm, execute:

npm install --save react@^16.0.0 react-dom@^16.0.0

Nós também fornecemos compilações UMD do React via CDN:

<script crossorigin src="https://unpkg.com/react@16/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>

Consulte a documentação para instruções detalhadas de instalação.

Atualização

Embora o React 16 inclua mudanças internas significativas, em termos de atualização, você pode pensar nisso como qualquer outro grande lançamento do React. Estamos servindo o React 16 aos usuários do Facebook e do Messenger.com desde o início deste ano, e lançamos várias versões beta e candidata à produção para eliminar problemas adicionais. Com pequenas exceções, se sua aplicação rodar na versão 15.6 sem nenhum aviso, ele deverá funcionar na versão 16.

Para as depreciações listadas abaixo na seção empacotamento, codemods estão disponíveis para automaticamente atualizar seu código. Consulte a publicação 15.5.0 no blog para mais informações, ou pesquise por codemods no projeto react-codemod.

Novas depreciações

A hidratação de um contêiner renderizado pelo servidor agora possui uma API explícita. Se você está recebendo HTML renderizado no servidor, use ReactDOM.hydrate no lugar de ReactDOM.render. Continue usando ReactDOM.render apenas se você estiver fazendo renderização no cliente.

React Addons

Como foi previamente anunciado, estamos descontinuando o suporte para React Addons. Esperamos que a versão mais recente de cada addon (exceto react-addons-perf; veja abaixo) funcione no futuro próximo, mas não publicaremos atualizações adicionais.

Consulte o anúncio anterior para obter sugestões de como migrar.

react-addons-perf não mais funcionará no React 16. É provável o lançamento de uma nova versão desta ferramenta no futuro. Enquanto isso, você pode usar a ferramenta de análise de performance do seu navegador para perfilar os componentes React.

Quebras de compatibilidade

React 16 inclui várias pequenas quebras de compatibilidade. Elas afetam apenas casos de uso incomuns e não esperamos que eles quebrem a maioria das aplicações.

  • React 15 tinha suporte limitado e não documentado para error boundaries usando o unstable_handleError. Este método foi renomeado para componentDidCatch. Você pode usar um codemod para migrar automaticamente para a nova API.
  • ReactDOM.render e ReactDOM.unstable_renderSubtreeIntoContainer agora retornam null se forem chamados dentro de um método do ciclo de vida. Para evitar isso, você pode usar portais ou refs.
  • setState:

    • Chamar setState com null não mais disparará uma atualização. Isto permite a você decidir em uma função de atualização se deseja re-renderizar.
    • Chamar setState diretamente no render sempre causará uma atualização. Este não era o comportamento anterior. Independentemente, você não deve chamar o setState no render.
    • Função de retorno do setState (segundo argumento) agora é disparada imediatamente após o componentDidMount / componentDidUpdate em vez de depois que todos os componentes tenham renderizado.
  • Quando substituir <A /> por <B />, B.componentWillMount agora será chamado sempre antes de A.componentWillUnmount. Anteriormente, A.componentWillUnmount poderia ser chamado antes em alguns casos.
  • Anteriormente, alterar a ref para um componente sempre desanexaria a ref antes que a renderização desse componente fosse chamada. Agora, alteramos a ref mais tarde, ao aplicar as alterações no DOM.
  • Não é seguro re-renderizar em um contêiner que foi modificado por algo diferente do React. Isso funcionou anteriormente em alguns casos, mas nunca foi suportado. Agora emitimos um aviso neste caso. Em vez disso, você deve limpar sua árvore de componentes usando ReactDOM.unmountComponentAtNode. Veja este exemplo.
  • O ciclo de vida componentDidUpdate não recebe mais o parâmetro prevContext. (Veja #8631)
  • Shallow renderer não chama mais o componentDidUpdate porque DOM refs não estão mais disponíveis. Isso também o torna consistente com o componentDidMount (que também não é chamado nas versões anteriores).
  • Shallow renderer não implementa mais unstable_batchedUpdates.
  • ReactDOM.unstable_batchedUpdates agora recebe apenas um argumento extra após o retorno de chamada.

Empacotamento

  • Não há mais react/lib/* e react-dom/lib/*. Mesmo em ambientes CommonJS, React e ReactDOM são pré-compilados para arquivos únicos (“flat bundles”). Se você usou alguma funcionalidade interna do React não documentada, e elas não funcionam mais, nos informe sobre seu caso específico em uma nova issue, que tentaremos descobrir uma estratégia de migração para você.
  • Não existe mais a versão react-with-addons.js. Todos os addons compatíveis serão publicados separadamente no npm, e terão versão de navegador de arquivo único caso necessite.
  • As depreciações introduzidas na versão 15.x foram removidas do pacote principal. React.createClass está disponível como create-react-class, React.PropTypes como prop-types, React.DOM como react-dom-factories, react-addons-test-utils como react-dom/test-utils, e shallow renderer como react-test-renderer/shallow. Consulte as publicações 15.5.0 e 15.6.0 no blog para obter instruções de migração de código e codemods.
  • Os nomes e caminhos para as compilações de navegador de arquivo único foram alterados para enfatizar a diferença entre as compilações de desenvolvimento e produção. Por exemplo:

    • 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.js → react-dom/umd/react-dom.production.min.js

Requisitos do ambiente JavaScript

React 16 depende dos tipos de coleção Map e Set. Se você suporta navegadores e dispositivos mais antigos que ainda não os fornecem nativamente (por exemplo, IE <11), considere incluir um polyfill global na compilação de sua aplicação, como core-js ou babel-polyfill.

Um ambiente para o React 16 usando polyfill do core-js para oferecer suporte a navegadores mais antigos deve se parecer com:

import 'core-js/es6/map';
import 'core-js/es6/set';

import React from 'react';
import ReactDOM from 'react-dom';

ReactDOM.render(
  <h1>Hello, world!</h1>,
  document.getElementById('root')
);

React também depende de requestAnimationFrame (mesmo em ambientes de teste).
Você pode usar o pacote raf para injetar requestAnimationFrame:

import 'raf/polyfill';

Agradecimentos

Como sempre, este lançamento não seria possível sem nossos contribuidores de código aberto. Agradecemos a todos que reportaram problemas, abriram PRs, responderam às issues, escreveram documentação e muito mais!

Agradecimentos especiais para os nossos contribuidores oficiais, especialmente por seus esforços heróicos nas últimas semanas durante o ciclo de pré-lançamento: Brandon Dail, Jason Quense, Nathan Hunzaker e Sasha Aickin.