Tutorial React: Componentes, Hooks e Desempenho
Publicados: 2022-03-11Como foi apontado na primeira parte do nosso tutorial do React, começar com o React é relativamente fácil. Comece usando Create React App (CRA), inicie um novo projeto e comece a desenvolver. Infelizmente, com o tempo, você pode se deparar com uma situação em que seu código se tornará bastante difícil de manter, especialmente se você for novo no React. Os componentes podem ficar desnecessariamente grandes ou você pode acabar com elementos que podem ser componentes, mas não são, então você pode acabar escrevendo código repetitivo aqui e ali.
É aí que você deve tentar realmente iniciar sua jornada React—começando a pensar em soluções de desenvolvimento React.
Sempre que você aborda um novo aplicativo, um novo design que você precisa transformar em um aplicativo React mais tarde, primeiro tente decidir quais componentes estarão em seu esboço, como você pode separar o esboço para torná-lo mais fácil de gerenciar e quais elementos são repetitivo (ou seu comportamento, pelo menos). Tente evitar adicionar código que possa ser “útil no futuro” – pode ser tentador, mas esse futuro pode nunca chegar e você manterá essa função/componente genérico extra que tem muitas opções configuráveis.
Além disso, se um componente for maior que, digamos, 2-3 alturas de janela, talvez valha a pena separá-lo (se possível) - pois será mais fácil lê-lo mais tarde.
Componentes controlados vs. não controlados em React
Na maioria dos aplicativos, há necessidade de entrada e alguma forma de interação com os usuários, permitindo que eles digitem algo, carreguem um arquivo, selecionem um campo e assim por diante. O React lida com a interação do usuário de duas maneiras distintas – componentes controlados e não controlados .
O valor dos componentes controlados, como o próprio nome sugere, é controlado pelo React fornecendo um valor ao elemento que interage com o usuário, enquanto os elementos não controlados não recebem uma propriedade value. Graças a isso, temos uma única fonte de verdade que é o estado React, então não há incompatibilidade entre o que estamos vendo na tela e o que temos atualmente em nosso estado. O desenvolvedor precisa passar uma função que responderá à interação do usuário com um formulário, que mudará seu estado.
class ControlledInput extends React.Component { state = { value: "" }; onChange = (e) => this.setState({ value: e.target.value }); render() { return ( <input value={this.state.value} onChange={this.onChange}/> ); } }
Em componentes React não controlados, não nos importamos como o valor muda, mas se quisermos saber o valor exato, simplesmente acessamos através de ref.
class UncontrolledInput extends React.Component { input = React.createRef(); getValue = () => { console.log(this.input.current.value); }; render() { return ( <input ref={this.input}/> ); } }
Então, qual deve ser usado quando? Eu diria que componentes controlados são o caminho a seguir na maioria dos casos, mas existem algumas exceções. Por exemplo, um caso em que você precisa usar componentes não controlados no React é a entrada do tipo de file
, pois seu valor é somente leitura e não pode ser definido programaticamente (é necessária a interação do usuário). Além disso, acho os componentes controlados mais fáceis de ler e mais fáceis de trabalhar. Fazer a validação para componentes controlados é baseado na rerenderização, o estado pode ser alterado e podemos indicar facilmente que há algo errado com a entrada (por exemplo, formato ou vazio).
Referências
Já mencionamos refs
, que são um recurso especial que estava disponível em componentes de classe até os ganchos aparecerem na versão 16.8.
Refs pode dar ao desenvolvedor acesso a um componente React ou elemento DOM (dependendo do tipo onde anexamos ref) por meio de referência. É considerado uma boa prática tentar evitá-los e usá-los apenas em cenários obrigatórios, pois tornam o código um pouco mais difícil de ler e interrompem o fluxo de dados de cima para baixo. No entanto, há casos em que eles são necessários, especialmente em elementos DOM (por exemplo, mudando o foco programaticamente). Ao anexar a um elemento de componente React, você pode usar livremente métodos de dentro desse componente ao qual está se referindo. Ainda assim, essa prática deve ser evitada, pois existem maneiras melhores de lidar com isso (por exemplo, elevando o estado e movendo funções para componentes pai).
Refs também têm três maneiras diferentes de serem realizadas:
- Usando um literal de string (herdado e deve ser evitado),
- Usando uma função de retorno de chamada que está sendo definida no atributo ref,
- Criando ref como
React.createRef()
e ligando-o a uma propriedade de classe e acessando-o por meio dela (esteja ciente de que as referências estarão disponíveis no ciclo de vida componentDidMount).
Finalmente, há casos em que refs não são passados e momentos em que você deseja acessar um elemento de referência mais profundo do componente atual (por exemplo, você tem um componente <Button>
que possui um elemento DOM <input>
interno e agora você estão em um componente <Row>
e do componente de linha você deseja ter acesso para inserir a função de foco do DOM. É aí que você usaria forwardRef
).
Um caso em que a referência não está sendo transmitida é quando há um componente de ordem superior sendo usado em um componente - o motivo é bastante compreensível, pois ref
NÃO é um prop
(semelhante a key
), portanto, não está sendo transmitido, portanto será estar referenciando o HOC
em vez do componente que está sendo encapsulado por ele. Nesse caso, podemos usar React.forwardRef
que recebe props e refs como argumentos, que podem ser atribuídos a prop
e passados para o componente que queremos acessar.
function withNewReference(Component) { class Hoc extends React.Component { render() { const {forwardedRef, ...props} = this.props; return <Component ref={forwardedRef} {...props}/>; } } return React.forwardRef((props, ref) => { return <Hoc {...props} forwardedRef={ref} />; }); }
Limites de erro
Quanto mais complexas as coisas ficam, maior a probabilidade de que algo dê errado. É por isso que os limites de erro fazem parte do React. Então, como eles funcionam?
Se algo der errado e não houver limite de erro como pai, isso resultará na falha de todo o aplicativo React. É melhor não exibir informações do que enganar os usuários e exibir informações erradas, mas isso não significa necessariamente que você deve travar todo o aplicativo e mostrar uma tela branca. Com limites de erro, você tem um grau adicional de flexibilidade que pode ser usado. Você pode usar um em todo o aplicativo e exibir uma mensagem de erro ou usá-lo em alguns widgets e simplesmente não exibi-los ou exibir uma pequena quantidade de informações no lugar desses widgets.
Lembre-se de que é apenas sobre problemas com código declarativo em vez de código imperativo que você escreve para lidar com alguns eventos ou chamadas. Para isso, você ainda deve usar a abordagem try/catch normal.
Os limites de erro também são um local onde você pode enviar informações para o Error Logger que você usa (no método de ciclo de vida componentDidCatch
).
class ErrorBoundary extends React.Component { state = { hasError: false }; static getDerivedStateFromError(error) { return { hasError: true }; } componentDidCatch(error, info) { logToErrorLogger(error, info); } render() { if (this.state.hasError) { return <div>Help, something went wrong.</div>; } return this.props.children; } }
Componentes de ordem superior
Componentes de ordem superior (HOC) são frequentemente mencionados no React e são um padrão muito popular, que você provavelmente usará (ou já usou). Se você estiver familiarizado com HOCs, provavelmente já viu withNavigation, connect, withRouter
em muitas bibliotecas.
HOCs são apenas funções que recebem um componente como argumento e retornarão um novo componente com recursos estendidos em comparação com aquele sem o wrapper HOC. Graças a isso, você pode obter algumas funções facilmente extensíveis que podem aprimorar seus componentes (por exemplo, acesso à navegação). Os HOCs também podem assumir algumas formas chamadas dependendo do que temos, o único argumento sempre necessário é um componente, mas pode receber argumentos extras - algumas opções, ou como em connect
, você primeiro invoca uma função com configurações que depois retorna uma função que recebe um componente de argumento e retorna HOC.
Há algumas coisas que você pode adicionar e deve evitar:
- Adicione um nome de exibição para sua função HOC wrapper (para que você saiba que é, de fato, um HOC alterando o nome de exibição do componente HOC).
- Não use HOC dentro de um método de renderização - você já deve estar usando um componente aprimorado dentro dele, em vez de criar um novo componente HOC lá, devido a remontá-lo o tempo todo e perder seu estado atual.
- Métodos estáticos não são copiados, então se você quiser ter alguns métodos estáticos dentro de seu HOC recém-criado, você precisa copiá-los sobre você mesmo.
- As Refs mencionadas não são passadas, então use
React.forwardRef
como mencionado anteriormente para resolver tais problemas.
export function importantHoc() { return (Component) => class extends React.Component { importantFunction = () => { console.log("Very Important Function"); }; render() { return ( <Component {...this.props} importantFunction={this.importantFunction} /> ); } }; }
Estilo
O estilo não está necessariamente relacionado ao React em si, mas vale a pena mencionar por vários motivos.
Em primeiro lugar, os estilos CSS/inline regulares se aplicam aqui normalmente e você pode simplesmente adicionar nomes de classe de CSS no atributo className, e ele funcionará corretamente. O estilo inline é um pouco diferente do estilo HTML normal. A string não está sendo passada com estilos, mas sim com objetos com valores corretos para cada um. Os atributos de estilo também são camelCased, então border-radius se torna borderRadius e assim por diante.
O React parece ter popularizado algumas soluções que se tornaram comuns não apenas no React, como módulos CSS que foram recentemente integrados ao CRA, onde você pode simplesmente importar name.modules.css
e usar suas classes como propriedades para estilizar seu componente (alguns IDEs , por exemplo, WebStorm, também possuem Autocomplete para isso, que informa quais nomes estão disponíveis).
Outra solução que também é popular no React é o CSS-in-JS (por exemplo, a biblioteca de emotion
). Apenas para salientar novamente, módulos CSS e emoção (ou CSS-in-JS em geral) não estão limitados ao React.
Ganchos em React
Hooks são possivelmente a adição mais aguardada ao React desde a reescrita. O produto faz jus ao hype? Da minha perspectiva, sim, pois eles realmente são um ótimo recurso. São essencialmente funções que abrem novas oportunidades, como:
- Permite a remoção de muitos componentes de
class
que usamos apenas porque não poderíamos ter, por exemplo, um estado local ou referência, para que o código de um componente pareça mais fácil de ler. - Permite que você use menos código para o mesmo efeito.
- Torna as funções mais fáceis de pensar e testar, por exemplo, usando a biblioteca react-testing.
- Também pode receber parâmetros, e o resultado de um pode ser facilmente usado por outro gancho (por exemplo,
setState
deuseState
emuseEffect
). - Minifica muito melhor do que classes, que tendem a ser um pouco mais problemáticas para minificadores.
- Pode remover HOCs e renderizar padrões de adereços em seu aplicativo que introduziram novos problemas, apesar de terem sido projetados para resolver outros.
- Capaz de ser customizado por qualquer desenvolvedor React qualificado.
Existem alguns ganchos do React incluídos como padrão. Os três básicos são useState
, useEffect
e useContext
. Existem também vários adicionais, por exemplo, useRef
e useMemo
, mas por enquanto, vamos nos concentrar no básico.
Vamos dar uma olhada em useState
e vamos usá-lo para criar um exemplo de um contador direto. Como funciona? Bem, basicamente, toda a construção é realmente direta e se parece com:
export function Counter() { const [counter, setCounter] = React.useState(0); return ( <div> {counter} <button onClick={() => setCounter(counter + 1)}>+</button> </div> ); };
Ele é invocado com initialState
(valor) e retorna um array com dois elementos. Graças à atribuição de desestruturação de arrays, podemos atribuir as variáveis a esses elementos imediatamente. O primeiro é sempre o último estado após as atualizações, enquanto o outro é uma função que usaremos para atualizar o valor. Parece bastante fácil, não é?
Além disso, devido ao fato de que esses componentes costumavam ser chamados de componentes funcionais sem estado, esse nome não é mais apropriado, pois eles podem ter um estado como mostrado acima. Portanto, os nomes de componentes de classe e componentes de função parecem estar mais alinhados com o que eles realmente fazem, pelo menos a partir de 16.8.0.
A função de atualização (no nosso caso setCounter
), também pode ser usada como uma função que tomará o valor anterior como argumento da seguinte forma:
<button onClick={() => setCounter(prevCounter => prevCounter + 1)}>+</button> <button onClick={() => setCounter(prevCounter => prevCounter - 1)}>-</button>
No entanto, ao contrário do componente da classe this.setState
que estava fazendo uma mesclagem superficial, definir a função ( setCounter
em nosso caso) está substituindo todo o estado.
Além disso, initialState
também pode ser uma função, não apenas um valor simples. Isso tem seus próprios benefícios, pois essa função será executada apenas durante a renderização inicial do componente e, depois disso, não será mais invocada.

const [counter, setCounter] = useState(() => calculateComplexInitialValue());
Finalmente, se formos usar setCounter
com exatamente o mesmo valor que tínhamos no mesmo momento no estado atual ( counter
), então o componente não será renderizado novamente.
Por outro lado, useEffect
é adicionar efeitos colaterais ao nosso componente funcional, sejam assinaturas, chamadas de API, temporizadores ou qualquer coisa que possamos achar útil. Qualquer função que passarmos para useEffect
será executada após a renderização, e o fará após cada renderização, a menos que adicionemos uma limitação sobre quais alterações de propriedades devem ser executadas novamente como um segundo argumento da função. Se quisermos executá-lo apenas na montagem e limpar na desmontagem, basta passar um array vazio nele.
const fetchApi = async () => { const value = await fetch("https://jsonplaceholder.typicode.com/todos/1"); console.log(await value.json()); }; export function Counter() { const [counter, setCounter] = useState(0); useEffect(() => { fetchApi(); }, []); return ( <div> {counter} <button onClick={() => setCounter(prevCounter => prevCounter + 1)}>+</button> <button onClick={() => setCounter(prevCounter => prevCounter - 1)}>-</button> </div> ); };
O código acima será executado apenas uma vez devido a um array vazio como segundo argumento. Basicamente, é algo como componentDidMount
nesse caso, mas é acionado um pouco mais tarde. Se você quiser ter um gancho semelhante que é chamado antes da pintura do navegador, use useLayoutEffect
, mas essas atualizações serão aplicadas de forma síncrona, diferente de useEffect
.
useContext
parece ser o mais fácil de entender, pois fornece para qual contexto queremos acessar (um objeto que foi retornado pela função createContext
) e, em troca, nos fornece o valor para esse contexto.
const context = useContext(Context);
Finalmente, para escrever seu próprio gancho, você pode simplesmente escrever algo como o seguinte:
function useWindowWidth() { let [windowWidth, setWindowWidth] = useState(window.innerWidth); function handleResize() { setWindowWidth(window.innerWidth); } useEffect(() => { window.addEventListener('resize', handleResize); return () => window.removeEventListener('resize', handleResize); }, []); return windowWidth; }
Basicamente, estamos usando o hook useState
regular para o qual estamos atribuindo como valor inicial a largura da janela. Então, em useEffect,
estamos adicionando um ouvinte que acionará handleResize
em cada redimensionamento de janela. Também limpamos depois que o componente será desmontado (veja o retorno em useEffect
). Fácil?
Nota: O uso da palavra em todos os ganchos é importante. É usado porque permite que o React verifique se você não está fazendo algo ruim, por exemplo, chamar ganchos de funções JS normais.
Tipos de Verificação
O React tinha sua própria verificação de props, antes que Flow e TypeScript fossem uma opção.
PropTypes verifica se as propriedades (props) que são recebidas por um componente React e verifica se estão de acordo com o que temos. Sempre que ocorrer uma situação diferente (por exemplo, objeto em vez de um array), receberemos um aviso no console. É importante observar que os PropTypes são verificados apenas no modo de desenvolvimento devido ao impacto no desempenho e ao aviso do console mencionado anteriormente.
A partir do React 15.5, os PropTypes estão em um pacote diferente que precisa ser instalado separadamente. Eles são declarados ao longo das propriedades em uma propriedade estática chamada propTypes
(surpresa), combinando-os com defaultProps
que são usados se as propriedades forem indefinidas ( undefined é o único caso). DefaultProps não estão relacionados a PropTypes, mas podem resolver alguns avisos que podem aparecer devido a PropTypes.
As outras duas opções são Flow e TypeScript, e são muito mais populares hoje em dia (especialmente TypeScript).
- TypeScript é um superconjunto tipado de JavaScript, desenvolvido pela Microsoft, que pode verificar erros antes mesmo de um aplicativo ser executado e fornece funcionalidade de preenchimento automático superior para desenvolvimento. Também melhora muito a refatoração. Devido ao suporte da Microsoft, que tem vasta experiência com linguagens digitadas, também é uma escolha bastante segura.
- Flow não é uma linguagem, ao contrário do TypeScript. É um verificador de tipo estático para JavaScript, portanto, é mais parecido com uma ferramenta que você inclui em JavaScript do que com uma linguagem. Toda a ideia por trás do Flow é bastante semelhante ao que o TypeScript oferece. Ele permite que você adicione tipos para que seja menos provável que haja erros antes de executar o código. Assim como o TypeScript, o Flow agora é suportado no CRA (Create React App) desde o início.
Pessoalmente, acho o TypeScript mais rápido (praticamente instantâneo), especialmente no autocomplete, que parece um pouco mais lento com o Flow. Vale a pena notar que IDEs como o WebStorm, que eu uso pessoalmente, empregam uma CLI para integração com o Flow. No entanto, parece ainda mais fácil integrar o uso opcional em arquivos, onde você simplesmente adiciona // @flow
no início do arquivo para iniciar a verificação de tipo. Além disso, pelo que posso dizer, parece que o TypeScript venceu a batalha contra o Flow no final - é muito mais popular agora, e algumas das bibliotecas mais populares estão sendo refatoradas do Flow para o TypeScript.
Existem mais algumas opções, mencionadas também na documentação oficial, como Reason (desenvolvido pelo Facebook e ganhando popularidade na comunidade React), Kotlin (linguagem desenvolvida pela JetBrains) e muito mais.
Obviamente, para desenvolvedores front-end, a abordagem mais fácil seria entrar e começar a usar Flow e TypeScript, em vez de mudar para Kotlin ou F#. No entanto, para desenvolvedores de back-end que estão fazendo a transição para front-end, eles podem ser mais fáceis de começar.
Desempenho de Produção e Reação
A mudança mais básica e óbvia que você precisa fazer para o modo de produção é mudar para “produção” para DefinePlugin
e adicionar UglifyJsPlugin
no caso de Webpack. No caso do CRA, é tão simples quanto usar npm run build
(que estará executando react react-scripts build
). Esteja ciente de que o Webpack e o CRA não são as únicas opções, pois você pode usar outras ferramentas de compilação como o Brunch. Isso geralmente é abordado na documentação oficial, seja na documentação oficial do React ou na documentação de uma ferramenta específica. Para certificar-se de que o modo está configurado corretamente, você pode usar o React Developer Tools, que lhe dará uma indicação de que tipo de compilação você está usando (produção versus desenvolvimento). As etapas mencionadas acima farão com que seu aplicativo seja executado sem verificações e avisos provenientes do React e o próprio pacote também será minimizado.
Há mais algumas coisas que você pode fazer para o seu aplicativo React. O que você faz com o arquivo JS que é construído? Você pode começar com apenas “bundle.js” se o tamanho for relativamente pequeno, ou talvez fazer algo como “fornecedor + pacote” ou talvez “fornecedor + menor parte necessária + importar coisas quando necessário”. Isso é útil quando você está lidando com um aplicativo muito grande e não precisa importar tudo no início. Esteja ciente de que agrupar algum código JavaScript no pacote principal que nem está sendo usado simplesmente aumentará o tamanho do pacote e tornará o carregamento do aplicativo mais lento no início.
Os pacotes de fornecedores podem ser úteis se você estiver planejando congelar as versões das bibliotecas ao perceber que elas podem não mudar por um longo tempo (se alguma vez). Além disso, arquivos maiores são melhores no gzip, portanto, o benefício que você obtém da separação às vezes pode não valer a pena. Depende do tamanho do arquivo e, às vezes, você simplesmente precisará experimentá-lo.
Divisão de código
A divisão de código pode aparecer de mais maneiras do que as sugeridas aqui, mas vamos nos concentrar no que temos disponível no CRA e no próprio React. Basicamente, para dividir o código em pedaços diferentes, podemos usar import()
que funciona graças ao Webpack (o próprio import
é uma proposta no estágio 3 a partir de agora, então ainda não faz parte do padrão da linguagem). Sempre que o Webpack vir import
, ele saberá que precisa iniciar a divisão de código neste estágio e não poderá incluí-lo no pacote principal (o código que está dentro do import).
Agora podemos conectá-lo com React.lazy()
que requer import()
com um caminho de arquivo contendo o componente que precisa ser renderizado naquele local. Em seguida, podemos usar React.suspense()
que exibirá um componente diferente naquele local até que o componente importado seja carregado. Alguém pode se perguntar; se estamos importando um único componente, por que precisaríamos dele?
Esse não é bem o caso, já que React.lazy()
mostrará o componente que import()
, mas import()
pode buscar um pedaço maior do que aquele único componente. Por exemplo, esse componente específico pode ter outras bibliotecas a reboque, mais código etc., portanto, um arquivo não é necessário - pode ser muitos outros arquivos agrupados. Finalmente, podemos agrupar tudo isso em ErrorBoundary
(você pode encontrar o código em nossa seção sobre limites de erro) que servirá como um substituto se algo falhar com o componente que queremos importar (por exemplo, se houver um erro de rede).
import ErrorBoundary from './ErrorBoundary'; const ComponentOne = React.lazy(() => import('./ComponentOne')); function MyComponent() { return ( <ErrorBoundary> <React.Suspense fallback={<div>Loading...</div>}> <ComponentOne/> </React.Suspense> </ErrorBoundary> ); }
Este é um exemplo básico, mas obviamente você pode fazer mais. Você pode usar import
e React.lazy
para divisão dinâmica de rotas (por exemplo, admin vs. usuário comum, ou apenas caminhos realmente grandes que trazem muito). Esteja ciente de que o React.lazy
suporta apenas exportações padrão a partir de agora e não suporta renderização do lado do servidor.
Desempenho do Código Reagir
Em relação ao desempenho, se o seu aplicativo React estiver lento, existem duas ferramentas que podem ajudá-lo a descobrir o problema.
O primeiro é o Chrome Performance Tab, que lhe dirá o que acontece com cada componente (por exemplo, montar, atualizar). Graças a isso, você deve ser capaz de identificar qual componente está apresentando problemas de desempenho e otimizá-lo.
A outra opção é usar o DevTools Profiler que ficou disponível no React 16.5+, e com a cooperação de shouldComponentUpdate (ou PureComponent, que foi explicado na parte um deste tutorial), podemos melhorar o desempenho de alguns componentes críticos.
Obviamente, empregar as melhores práticas básicas para a web é ideal, como debounce de alguns eventos (por exemplo, scroll), ser cauteloso com animações (usando transform em vez de alterar a altura e animar) e assim por diante. O uso de melhores práticas pode ser negligenciado com muita facilidade, especialmente se você está apenas começando a se familiarizar com o React.
O estado do React em 2019 e além
Se fôssemos discutir o futuro do React, pessoalmente, eu não ficaria muito preocupado. Do meu ponto de vista, o React não terá problemas para manter seu trono em 2019 e além.
O React tem uma posição tão forte, apoiada por uma grande comunidade de seguidores, que será difícil destronar. A Comunidade React é ótima, não está ficando sem ideias, e a equipe principal está constantemente trabalhando para melhorar o React, adicionando novos recursos e corrigindo problemas antigos. O React também é apoiado por uma grande empresa, mas os problemas de licenciamento desapareceram - ele é licenciado pelo MIT agora.
Sim, há algumas coisas que devem ser alteradas ou melhoradas; por exemplo, tornando o React um pouco menor (uma das medidas mencionadas é a remoção de eventos sintéticos) ou renomeando className
para class.
Obviamente, mesmo essas alterações aparentemente menores podem causar problemas, como afetar a compatibilidade do navegador. Pessoalmente, também me pergunto o que acontecerá quando o WebComponent ganhar mais popularidade, pois pode aumentar algumas das coisas com as quais o React costuma ser usado hoje. Não acredito que eles sejam um substituto definitivo, mas acredito que possam se complementar muito bem.
Quanto ao curto prazo, os ganchos acabaram de chegar ao React. Essa é provavelmente a maior mudança desde que a reescrita aconteceu no React, pois eles abrirão muitas possibilidades e aprimorarão outros componentes de função (e eles estão realmente sendo divulgados agora).
Por último, como é o que tenho feito mais recentemente, há o React Native. Para mim, é uma ótima tecnologia que mudou muito nos últimos dois anos (a falta de um link nativo de reação foi provavelmente o maior problema para a maioria das pessoas, e obviamente havia muitos bugs). O React Native está tendo seu núcleo reescrito, e isso deve ser feito de maneira semelhante à reescrita do React (é tudo interno, nada ou quase nada deve ser alterado para os desenvolvedores). Renderização assíncrona, uma ponte mais rápida e leve entre nativo e JavaScript e muito mais.
Há muito o que esperar no ecossistema React, mas as atualizações de ganchos (e React Native se alguém ama celulares) são provavelmente as mudanças mais importantes que veremos em 2019.