A versão [16.8.0](https://github.com/facebook/react/releases/tag/v16.8.0), é o primeiro **release** que traz suporte estável aos **Hooks**. Com isso, simplificando a vida de programadores e curiosos. Permitindo o uso de estado e outros recursos da biblioteca sem escrever uma classe.## Regras dos Hooks- Apenas chame os Hooks **no nível mais alto**. Não chame Hooks dentro de **loops**, **condicionais** ou **funções aninhadas**. O React identifica os hooks de um componente pela ordem em que eles foram chamados. - Apenas chame os Hooks em **componentes funcionais**. Não chame Hooks em funções **JavaScript** comuns. (Há apenas um outro lugar válido para se chamar Hooks — dentro dos seus próprios Hooks customizados.)Confira o link para o [plugin do eslint](https://www.npmjs.com/package/eslint-plugin-react-hooks), para que as regras sejam revisadas automaticamente.## Tipos de Hooks- [Hook de estados](https://reactjs.org/docs/hooks-state.html) - **useState** - permite ler e armazenas as informações de maneira mais fácil e prática no estado, eliminando alguns componentes de classes e substituindo por componentes funcionais. - [Hook de efeitos](https://reactjs.org/docs/hooks-effect.html) - **useEffect** - utilizado para executar funções que necessitam ou realizam algum efeito no componente. Ex: **mutations**, **subscriptions**, **timers** e **logging**. Tem o mesmo efeito que os **componentDidMount** e **componentDidUpdate** tem nas classes. - [Hook customizado](https://reactjs.org/docs/hooks-custom.html) - Crie seus próprios **hooks** e extraia a lógica de um componente em funções reutilizáveis. - [Outros Hooks](https://reactjs.org/docs/hooks-reference.html) - Hooks nativos com funções específicas.Os Hooks existentes podem ser classificados como básicos e adicionais. Veja a lista abaixo:**Hooks básicos:**- [useState](https://pt-br.reactjs.org/docs/hooks-reference.html#usestate) - [useEffect](https://pt-br.reactjs.org/docs/hooks-reference.html#useeffect) - [useContext](https://pt-br.reactjs.org/docs/hooks-reference.html#usecontext)**Hooks adicionais:**- [useReducer](https://pt-br.reactjs.org/docs/hooks-reference.html#usereducer) - [useCallback](https://pt-br.reactjs.org/docs/hooks-reference.html#usecallback) - [useMemo](https://pt-br.reactjs.org/docs/hooks-reference.html#usememo) - [useRef](https://pt-br.reactjs.org/docs/hooks-reference.html#useref) - [useImperativeMethods](https://pt-br.reactjs.org/docs/hooks-reference.html#useimperativehandle) - [useMutationEffect](https://pt-br.reactjs.org/docs/hooks-reference.html#uselayouteffect) - [useLayoutEffect](https://pt-br.reactjs.org/docs/hooks-reference.html#usedebugvalue)## Hook de estadosVamos olhar o hook de estado. Abaixo veremos um exemplo:``` import React, { useState } from 'react'function Counter() { const [count, setCount] = useState(0) return ( Você clicou {count} vezes! setCount(count + 1)}>+1 ); }; ```O hook nesse caso é o **useState**. Ele está recebendo um estado inicial e retorna um array com dois valores. Sendo o primeiro valor o estado atual e o segundo uma função para atualizar esse estado. O **useState** não tem a funcionalidade idêntica ao **setState** que é utilizado em classes. Quando se é passado um objeto para o **setState**, o mesmo combina o valor que estamos passando com o antigo. Já no **useState**, todo o estado do hook será alterado, mas temos o mesmo efeito usando o operador de **spread**. Ex: useState({ ...oldState, ...newState }); .Exemplo de um objeto no estado inicial:``` function Counter() { const [state, setState] = useState({ nome: '', idade: 0 }) ... ) } ```Também, podemos chamar mais de uma vez o nosso hook **useState** no nosso componente.``` function Counter() { const [name, setName] = useState('') const [age, setAge] = useState(0) ... ) } ```## Hook de efeitosAgora vamos falar do hook **useEffect**. O mesmo permite que seu componente em forma de função tenha acesso aos métodos de ciclo de vida sem precisar refatorar seu componente para uma classe. Abaixo, um exemplo:``` import React, { useState, useEffect } from 'react'function Counter() { const [count, setCount] = useState(0) useEffect(() => { window.document.title = `Você clicou ${count} vezes!` }) return ( Você clicou {count} vezes! setCount(count + 1)}>+1)} ```O título será alterado de acordo com a atualização do estado do componente. O **useEffect** nesse contexto, seria o mesmo que o **ComponentDidMount** e também o **ComponentDidUpdate**. Será chamada a função passada tanto quando o componente é montado quando é atualizado.O **useEffect** te ajuda ao desmontar os recursos, exatamente como faria com **ComponentWillUnmount**.``` function Example() { const [x, setX] = useState(0); const [y, setY] = useState(0); useEffect(() => { const mouseMove = e => { setX(e.screenX) setY(e.screenY) } document.addEventListener('mousemove', mouseMove); return () => document.removeEventListener('mousemove', mouseMove); }) return O Mouse esta no {x}, {y}; } ```Acima temos o evento de **mousemove** configurado para alterar o estado do componente de acordo com o movimento do mouse e quando o componente for desmontado será rodado o **removeEventListener**. Também será chamada quando for detectado que o **useEffect** precisa rodar novamente, ou seja em cada render. A cada alteração no estado do componente nosso evento está sendo removido e adicionado novamente. Agora não queremos isso e precisamos que o evento seja adicionado na montagem e na desmontagem.Vamos utilizar o segundo argumento que o **useEffect** recebe, que é uma lista dos valores que devem mudar para que ele rode novamente. Passando uma lista vazia, ele irá rodar apenas quando é montado e a função de limpeza apenas quando é desmontado.``` function Example() { const [x, setX] = useState(0) const [y, setY] = useState(0) useEffect(() => { const mouseMove = e => { setX(e.clientX) setY(e.clientY) } document.addEventListener('mousemove', mouseMove); return () => document.removeEventListener('mousemove', mouseMove); }, []) // Mouse esta no {x}, {y}; } ```Os **Event listeners** serão chamados apenas quando precisamos. O segundo parâmetro pode ser utilizado para dizer quando nosso efeito vai rodar. Abaixo, um exemplo:``` function Status(props) { const [isOnline, setIsOnline] = useState(null); useEffect(() => { const handleStatusChange = status => setIsOnline(status.isOnline) API.subscribeToUserStatus(props.user.id, handleStatusChange) return () => API.unsubscribeFromUserStatus(props.user.id, handleStatusChange) }, [props.user.id]) // apenas se desinscreve caso props.friend.id mude } ```Quando friend.id for alterado, iremos chamar o **unsubscribeFromUserStatus** com id anterior e depois chamar o **subscribeToUserStatus** com id atual, assim temos consistência na limpeza dos recursos de forma simples.## Hook customizadoOs Hooks são totalmente desacoplados de componentes, o que nos permite combiná-los para criar novos hooks mais específicos e compartilhar lógica entre nossos componentes.Começaremos com o exemplo abaixo:``` import React, { useState, useEffect } from 'react';function Status(props) { const [isOnline, setIsOnline] = useState(null); useEffect(() => { const handleStatusChange = status => status.isOnline API.subscribeToUSerStatus(props.user.id, handleStatusChange) return () => API.unsubscribeFromUSerStatus(props.user.id, handleStatusChange) } }) if (isOnline === null) return 'Loading...'; return isOnline ? 'Online' : 'Offline'; } ```Também vamos precisar de uma lista de contatos e exibir seus respectivos status.``` import React, { useState, useEffect } from 'react';function UserListItem(props) { const [isOnline, setIsOnline] = useState(null); useEffect(() => { const handleStatusChange = status => status.isOnline ChatAPI.subscribeToUserStatus(props.user.id, handleStatusChange) return () => API.unsubscribeFromUserStatus(props.user.id, handleStatusChange) }) return {props.user.name}; } ```Com isso, temos uma repetição de código. Resolveremos isso, ao extrair a lógica repetida em um hook customizado.``` import React, { useState, useEffect } from 'react';function useUserStatus(userID) { const [isOnline, setIsOnline] = useState(null); useEffect(() => { const handleStatusChange = status => status.isOnline API.subscribeToUserStatus(userID, handleStatusChange) return () => API.unsubscribeFromUserStatus(userID, handleStatusChange) }) return isOnline; } ```Agora a lógica que tínhamos em nossos componentes, está em uma função separada (um padrão: que os hooks tenham o prefixo **use**). Abaixo, exemplo da utilização:``` function UserStatus(props) { const isOnline = useUserStatus(props.user.id) if (isOnline === null) return 'Loading...'; return isOnline ? 'Online' : 'Offline'; } `````` function UserListItem(props) { const isOnline = useUserStatus(props.user.id) return {props.user.name}; } ```Agora temos uma lógica simplificada. Também é possível criar hooks para lidar com bibliotecas externas:``` import React, { useState, useEffect } from 'react';const useObservable = (observable, initialValue) => { const [value, setValue] = useState(initialValue) useEffect(() => { const subscription = observable.subscribe({next: setValue}) return () => subscription.unsubscribe() }, [observable]) return value } ```Acima, a cada novo evento no **stream** do **observable** temos uma atualização no estado. Abaixo, um exemplo usando a bilbioteca **RxJS**.``` import React from 'react'; import { fromEvent } from 'rxjs'; import { map } from 'rxjs/operators'; import { useObservable } from './observableHook';const mouseTest = fromEvent(document, 'mousemove').pipe( map(e => [e.clientX, e.clientY]) );const App = () => { const [x,y] = useObservable(mouseTest, [0,0]); return Mouse x:{x} y:{y}; } ```## Considerações finaisNão foi falado muito sobre os **Outros Hooks**, mas podemos ver a listagem no ínício deste artigo. Mais sobre os **Hooks**, podem ser vistos na [documentação oficial](https://pt-br.reactjs.org/docs/hooks-intro.html) e em próximos artigos.
Na versão [16.3.0](https://github.com/facebook/react/releases/tag/v16.3.0), que foi lançada em 29 de março de 2018, teve a adição de novos métodos para o ciclo de vida dos componentes e nova API.## Métodos de ciclo de vidaNo ciclo de vida dos componentes existem métodos para controlarmos o fluxo de montar, atualizar e desmontar cada elemento. E com essa versão do **React**, três métodos estão sendo depreciados: **componentWillMount**, **componentWillReceiveProps**, e **componentWillUpdate**. E foram adicionados dois novos métodos:- **getDerivedStateFromProps** – adicionado como uma alternativa mais segura do método **componentWillReceiveProps**. 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** – adicionado para oferecer suporte à leitura segura de propriedades. Todo valor retornado por esse método é enviado ao **componentDidUpdate** que é o ciclo executado posteriormente.## Context APISempre existiu uma **Context API**, mas era instável e com diversos problemas relacionados à performance. Eu particularmente já usava para uma questão de tema e gostei muito da estabilide que veio nessa versão.Ao compartilhar informações entre componentes totalmente desconexos você terá que utilizar a arquitetura flux com **Redux**. Com a nova **Context API** conseguimos facilmente repassar informações de qualquer tipo entre diversos componentes do **React**.Precisaremos ver 3 coisas: **React.createContext**, **Provider** e **Consumer**.Abaixo, temos o componente filho **Title** e ainda não estamos usando a nova API de contexto.``` class App extends Component { state = { ttile: 'Esse é um título' } render() { const { title } = this.state; return ( {tenant && } ); } } ```Vamos começar 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.``` const ExampleContext = React.createContext('example'); ```A variável **ExampleContext** já pode ser considerada uma variável de contexto. Para alterar o seu valor, precisamos utilizar um componente chamado **Provider** que pertence à essa variável:``` render() { const { title } = this.state; return ( {title && } ); } ```Assim, criamos um **ExampleContext.Provider** com uma única propriedade chamada value que é responsável por prover o valor da variável de contexto.Agora o componente **Title**, consome o **ExampleContext**:``` function Title() { return ( {title => ( {title} )} ); } ```Com o **ThemeContext.Consumer** podemos utilizar esses dados e trabalhar com uma técnica chamada [render props](https://reactjs.org/docs/render-props.html).Sendo assim, 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.Para retornar o valor padrão que informamos na criação da variável **ExampleContext**, o componente não deverá possuir um **Provedor** correspondente acima dele na árvore. Isso pode ser útil para testar componentes isoladamente sem envolvê-los.``` render() { const { title } = this.state; return ( ); }// Saída: example ```Mais pode ser visto na [documentação oficial](https://reactjs.org/docs/context.html).## Considerações finaisEntão vamos continuar precisando de um gerenciamento de estado mais complexo como o **Redux** e temos a API de contexto quando for necessário compartilhar algumas informações entre componentes.Agora é ficar ligado nos novos métodos e prestar atenção nos que foram depreciados. A biblioteca está evoluindo muito bem e vamos botar a mão na massa.
A versão [16.0.0](https://github.com/facebook/react/releases/tag/v16.0.0), foi lançado em 26 de setembro de 2017, e trouxe mudanças significativas até o momento.## Polêmica com a licençaPor um período os desenvolvedores ficaram preocupados com a ideia da biblioteca ter adotado a licença BSD+Patents. Tudo ficou na paz, quando o **React 16** foi disponível sob a licença MIT. A versão 15.6.2 também foi publicado com essa licença, para que não fosse preciso que as aplicações fossem atualizadas imediatamente.## Novo tamanhoAgora mesmo com novas funcionalidades, o tamanho diminuiu cerca de 32%, se comparado com a versão 15.6.1.**Versão 15**- react - 20.7kb (6.9kb com gzip) - react-dom - 141kb (42.9kb com gzip) - react + react-dom - 161.7 kb (49.8 kb com gzip)**Versão 16**- react - 5.3kb (2.2kb com gzip) - react-dom - 103.7kb (32.6kb com gzip) - react + react-dom - 109 kb (34.8 kb com gzip)## Tratamento de errosAntes tínhamos o problema que ao ter um erro durante a renderização, toda a árvore de componentes era desmontada. Agora é possível capturar os erros e substituir o componente. Quem não gosta de um try-catch? :)Temos então, o novo método **componentDidCatch**, que irá informar o erro para que possamos tratar com facilidade. Identificando um erro, podemos tratar no método **render**.``` componentDidCatch(error, info) { this.setState({ ...state, hasError: true }); // E você também tem 2 paramêtros para utilizar console.log(error); // o erro em si console.log(info); // contém o Component Stack }render() { if (this.state.hasError) { return Deu algo errado; } else { // retornando o componente ... } } ```Para mais detalhes, confira o artigo oficial sobre o [tratamento de erros no React 16](https://reactjs.org/blog/2017/07/26/error-handling-in-react-16.html).## Novos tipos de retorno de renderizaçãoAo trabalhar com **React**, o método **render** sempre deve retornar um único elemento. Querendo retonar uma lista de elementos, você deve criar um **container** para eles.Agora você pode retornar um **Array** de elementos. Por ser um Array, você ainda precisará adicionar o atributo **key** aos elementos.``` render() { return [ item 1, item 2, item 3, ]; } ```E também é possível retornar uma simples **String**:``` render() { return 'Meu nome é Hemerson'; } ```## PortalsAgora é possível inserir um elemento filho em um local diferente no DOM, fora da sua árvore principal.Exemplo:``````Com **Portals**, tendo um componente na div **main**, será possivel pegar este componente e renderizá-lo na div **modal**.Tendo um elemento que irá aparecer na página e reaparecer ao abrir uma modal, seria necessário chamar o componente em dois lugares (na página e na modal) e passar as propriedades para ele. Com **Portals** basta indicar o elemento que quer usar e onde quer exibí-lo. Querendo alterar alguma propriedade passada para o componente, só será preciso alterar em um lugar.Mais detalhes na [documentação](https://reactjs.org/docs/portals.html);## Renderização no lado do servidorGraças a reescrita, a renderização no lado do servidor ficou muito mais rápida. E agora com suporte a **streaming**, sendo possível enviar os dados de forma melhor e mais ágil para o navegador.Nesse artigo, pode ser visto as [melhorias no SSR](https://hackernoon.com/whats-new-with-server-side-rendering-in-react-16-9b0d78585d67).## Atributos personalizadosAtributos informados no HTML ou SVG que não fossem reconhecidos eram ignorados. Agora os mesmos são mantidos.``````## Nova arquiteturaAgora temos uma reescrita na arquitetura central da biblioteca, sendo conhecida como **Fiber**. O mesmo é responsável pela maioria dos novos recursos do React 16.Uma área que está tendo um bom foco é a renderização assíncrona, tendo uma estratégia para programar cooperativamente a renderização, entregando periodicamente a execução ao navegador. Com a renderização assíncrona, as aplicações são mais responsivas porque o React evita o bloqueio da árvore principal. Nessa versão 16.0.0 não foi ativado nenhum recurso assíncrono, para facilitar a migração para essa versão.Confira um exemplo de problema de [renderização assíncrona](https://twitter.com/acdlite/status/909926793536094209?ref_src=twsrc%5Etfw%7Ctwcamp%5Etweetembed%7Ctwterm%5E909926793536094209&ref_url=https%3A%2F%2Freactjs.org%2Fblog%2F2017%2F09%2F26%2Freact-v16.0.html).## Depreciações, mudanças, empacotamento e requisitos### DepreciaçõesPara hidratar um container renderizado pelo servidor agora tem uma API explicita. Renderizando o HTML pelo servidor, use **ReactDOM.hydrate** ao invés de **ReactDOM.render**. Use **ReactDOM.render** se renderizar pelo lado do cliente.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 serão atualizados. **react-addons-perf** não funciona no React 16, e é encorajado usar as [ferramentas do navegador para medir performance](https://reactjs.org/docs/optimizing-performance.html#profiling-components-with-the-chrome-performance-tab).### MudançasO React 16 depende dos tipos de coleção **Map** e **Set**. Se você precisa dar suporte para navegadores e dispositivos antigos que não suportam nativamente (por exemplo, IE ** por ****, **B.componentWillMount** agora vai sempre acontecer antes de **A.componentWillUnmount**. Antes, **A.componentWillUnmount** podia inicializar primeiro em certos casos. - Antes, mudar a referência de um componente sempre iria desmontar a referência antes que o renderização do componente fosse chamada. Agora, a referência é alterada depois, quando aplicadas as mudanças no DOM. - **componentDidUpdate** não recebe mais o parâmetro **prevContext**. - O renderizador superficial não é mais chamado no **componentDidUpdate** porque as referências DOM não estão disponíveis. Isso também o torna consistente com **componentDidMount**(que também não é chamado nas versões anteriores).## EmpacotamentoAgora não existe mais **react/lib/** e **react-dom/lib/**. Os nomes/caminhos mudaram para enfatizar a diferença entre os **builds** de produção e desenvolvimento:- react/dist/react.js → react/umd/react.development.js - react/dist/react.min.js → react/umd/react.production.min.js - react-dom/dist/react-dom.js → react-dom/umd/react-dom.development.js - react-dom/dist/react-dom.min.js → react-dom/umd/react-dom.production.min.js## Considerações finaisMuitas mudanças boas vieram e o React continua sendo muito usado nas aplicações. Pode conferir o artigo completo no blog oficial sobre a versão [16.0.0](https://reactjs.org/blog/2017/09/26/react-v16.0.html).
A biblioteca que é largamente usada no desenvolvimento front-end já está na versão [16.8.6](https://github.com/facebook/react/releases/tag/v16.8.6), que foi lançada em 27 de março deste ano.Para quem está começando com o **React**, vale saber que teve algumas mudanças significativas a partir da versão [16.0.0](https://github.com/facebook/react/releases/tag/v16.0.0), lançada em 26 de setembro de 2017 (veremos sobre isso no próximo artigo).Antes de tudo, vale saber da linha do tempo.## A Linha do tempoHá exatos seis anos (29 de maio de 2013), uma biblioteca JavaScript de código aberto, que foi desenvolvida pelo **Facebook**, era lançada. Sendo óbvio, estou falando da biblioteca **React**. Para ser mais preciso, a pessoa que está por trás dessa criação é [Jordan Walke](https://twitter.com/jordwalke) (Engenheiro de software na empresa Facebook).Tivemos o lançamento do [React Native](https://facebook.github.io/react-native/), em 26 de março de 2015.Em 18 de abril de 2017, o Facebook anunciou o [React Fiber](https://github.com/acdlite/react-fiber-architecture), um novo algoritmo `core` da biblioteca. Com o propósito de se tornar a base de qualquer melhoria futura e desenvolvimento de recursos da biblioteca **React**.No dia seguinte (19 de abril de 2017), foi lançado o [React 360](https://facebook.github.io/react-360/), para o público. Isso permitiu aos desenvolvedores que utilizam React, saltassem para o desenvolvimento de VR (Realidade Virtual).Por fim, temos a versão 16 e 16.8.6 da biblioteca, como mencionado no início desse artigo. Sem esquecer que na versão 16.8, temos o suporte estável na utilização de Hooks, que veremos nos próximos artigos.## A BibliotecaA biblioteca ganhou grande popularidade por ter o foco na criação de componentes de interface, ter uma grande empresa por trás, usar uma técnica que agradou à todos (Virtual-Dom) e ter uma pequena curva de aprendizado para quem já está acostumando com **JavaScript**.Abaixo, também veremos sobre a especificação JSX e micro bibliotecas que auxiliam o desenvolvimento com **React**.### Virtual-DOMÉ uma representação em JavaScript puro do DOM. Sendo assim, você manipula esse objeto e não o DOM de verdade. Quando o objeto virtual é atualizado, um algoritmo calcula a diferença entre o virtual-dom e o DOM real, alterando então os trechos do DOM.É mais produtivo criar os elementos DOM no JavaScript, processar eles e aplicá-los de uma só vez na arvore DOM do navegador. A biblioteca veio para facilitar isso, entre outras coisas.### JSXJSX é uma especificação de sintaxe para escrever JavaScript como se estivéssemos escrevendo XML.``` cont Example = React.createClass({ render: function() { return Olá, {this.props.name}; } });ReactDOM.render( , document.getElementById('main') ); ```Sem JSX:``` var Example = React.createClass({ displayName: 'Hello', render: function() { return React.createElement('div', null, 'Olá, ', this.props.name); } });ReactDOM.render( React.createElement(Example, {name: 'Hemerson'}), document.getElementById('main') ); ```### Micro-bibliotecasSendo apenas uma biblioteca, não seria possível criar aplicações complexas, apenas com **React**. Por isso, vamos falar um pouco nas micro-bibliotecas que ajudam muito no desenvolvimento.As mais utilizadas nos projetos são [react-router](https://reacttraining.com/react-router/) e [react-redux](https://react-redux.js.org/). Com elas, já é capaz de criar uma projeto SPA complexo.Cada vez mais o caminho tem sido separar as responsabilidades, por uma questão de manutenção, peso e mais.Nesse [link](https://github.com/enaqx/awesome-react), temos muitas micro-bibliotecas para nos ajudar.## Considerações finaisTenho gostado de utilizar o **React**, pela liberdade no desenvolvimento de componentes e pela estabilidade e flexibilidade da ferramenta. Nos dias de hoje, podemos usar no navegador, servidor e aplicativos móveis. A comunidade está empenhada no crescimento e melhorias. A cada ano temos evoluções consideráveis da biblioteca e ferramentas que utilizamos como suporte no desenvolvimento das aplicações.