Recentemente, o Facebook lançou oficialmente a versão 16.0 do React, junto com a reformulação do site e blogs oficiais, e a mudança da licença não só do React, mas do Jest, Flow e Immutable.js para open source MIT. Esta versão que foi trabalhada por mais de um ano, trouxe várias melhorias relevantes para a biblioteca, desde a reescritura do seu core – chamado de React Fiber – que tornou o código mais rápido e dinâmico, até as novas funcionalidades, como os Portais, Limites de Erros (Error Boundaries), Fragmentos e mais.
Vamos dar uma olhada nelas.
Error Boundaries (limites de erros)
Até o React 15, quando um erro JavaScript era disparado e o componente quebrava em execução, ficava difícil trazer uma resposta adequada para o usuário, já que o comportamento padrão do componente era ficar na tela, mesmo que quebrado. Com o React 16, isso mudou.
O primeiro ponto, é que componentes com erro agora são removidos da tela por padrão. Então, se tivermos um contador, por exemplo, e ele acabar tentando somar um inteiro com NaN e isso resultar em uma exceção, o componente é removido na tela.
Mas isso não é um comportamento bacana, não é mesmo? Exatamente por isso o Facebook introduziu o conceito de Error Boundaries. A ideia é que o desenvolvedor consiga delimitar uma “área de erro” e com isso, coletar informações e exibir uma tela de fallback para o usuário caso um erro aconteça, mostrando alguma mensagem mais elucidativa.
Tudo isso é feito através do novo método de ciclo de vida dos componentes, o componentDidCatch. Veja como é simples criar um componente de fallback genérico para aplicação com este pequeno exemplo, onde estamos criando um botão que propositalmente gera um erro:
// componente genérico de fallback com o componentDidCatch class ErrorBoundary extends React.Component { constructor(props) { super(props); this.state = { error: false } } componentDidCatch(error, info) { this.setState(state => ({...state, error: true})); } render() { if(this.state.error) { return <div>Oooops! Aconteceu alguma coisa errada!</div> } else { return this.props.children; } } } class Usuario extends React.Component { constructor(props) { super(props); } render() { return ( <div> {this.props.usuario.nome} </div> ) } } // Criamos um erro propositalmente para ver a UI de fallback class App extends React.Component { constructor(props) { super(props); this.state = { usuario: { nome: 'Diego Pinho' }, } this.throwError = this.throwError.bind(this); } throwError() { this.setState(state => ({ ...state, usuario: null })); } render() { return ( <div> <ErrorBoundary> <Usuario usuario = {this.state.usuario} /> <button onClick={this.throwError}>mudar nome</button> </ErrorBoundary> </div> ) } }
Você pode executar e editar este código no CodePen clicando aqui.
Fragmentos
Até então, tínhamos a necessidade de sempre encapsular os componentes em uma tag, como uma div, por exemplo. Agora não há mais essa necessidade. Conseguimos renderizar os componentes diretamente passando eles em um array no return do método render.
Por exemplo, se quisermos listar uma simples lista de nomes, basta fazer isso:
class App extends React.Component { render() { return [ <p key="1">João</p>, <p key="2">Maria</p>, <p key="3">Dagoberto</p> ] } }
Reparem que como estamos tratando de um array, precisamos indicar ao React como identificar de forma única cada um dos itens através da propriedade key. Mas além disso, outro aspecto interessante, é que também podemos renderizar textos diretamente.
class App extends React.Component { render() { return “Olá mundo!” } }
Você pode executar e editar este código no CodePen clicando aqui.
Portais
Os portais são outra novidade interessante. Com eles, conseguimos renderizar um elemento filho em um nó da DOM que existe fora da hierarquia do pai do componente. O caso comum é ter apenas um nó da DOM que usamos para mapear no React.render. Com isso, agora qualquer nó pode ser facilmente utilizado. Isso é excelente, por exemplo, para trabalharmos com modais, tooltips, hovercards e caixas de diálogo.
A mágica acontece através do método ReactDOM.createPortal. Ele aceita dois parâmetros: o primeiro é o componente React que desejamos renderizar e o segundo é qualquer nó da DOM.
Veja este exemplo para entender como podemos utilizá-lo.
Atributos Customizáveis
Quem nunca utilizou o atributo class ao invés do className nos componentes React que atire a primeira pedra. Até a versão 15, qualquer atributo que o React não conhecia, era simplesmente ignorado na hora que o componente era renderizado. Mas agora não mais. A partir desta versão, qualquer atributo é válido. Reparem que se criamos um atributo chamado “atributo” e colocamos um valor, ele inserido na DOM.
class App extends React.Component { render() { return ( <div atributo="olamundo" class="cor"> Olá mundo! </div> ); } }
Olhando o elemento com o DevTools:
O único porém, é que caso o atributo seja conhecido pelo React, precisaremos utilizar a nomenclatura correta, como no exemplo do class e className.
Você pode executar e editar este código no CodePen clicando aqui.
Conclusão
Estas foram algumas das melhorias trazidas para a biblioteca que vão ajudar no desenvolvimento do dia a dia. Além delas, também foram feitas melhorias no server-side rendering, empacotamento e tamanho do build, que teve uma redução de 30%. Também houveram algumas pouquíssimas mudanças de API, mas felizmente, a equipe do Facebook teve o cuidado de não quebrá-las.
Para mais informações, confira o post oficial do Facebook sobre o React 16.
Extra
Caso você queira explicações mais detalhadas sobre as melhorias, publiquei um curso GRATUITAMENTE no Udemy sobre o assunto. Para acessá-lo, basta clicar aqui.