React v16.8: O React com Hooks

06 de fevereiro de 2019 por Dan Abramov

Com o React 16.8, React Hooks tornam-se disponíveis em sua versão estável!

O Que São Hooks?

Hooks lhe permite utilizar estado e outras funcionalidades do React sem a necessidade de escrever uma classe. Assim como, você também pode criar o seus próprios Hooks para compartilhar e reutilizar sua lógica com estado entre componentes.

Se você nunca ouviu falar sobre Hooks antes, talvez você ache estes tópicos interessantes:

Você não precisa aprender Hooks agora. Hooks não quebra aplicações existentes, e nós não temos planos de remover o uso de classes do React. O Hooks FAQ descreve à adoção gradual da estratégia.

Sem Grandes Reescritas

Não recomendamos que você reescreva suas aplicações existentes, apenas para utilizar Hooks de uma hora para outra. Pelo contrário, tente utilizar Hooks em alguns de seus novos componentes, e deixe-nos saber o que você acha. Desenvolver utlizando Hooks, funcionará lado a lado ao código já existente qual faz uso de classes.

Posso usar Hooks hoje?

Sim! Iniciando com a versão 16.8.0, o React inclui a versão estável da implementação do React Hooks para:

  • React DOM
  • React DOM Servidor (React DOM Server)
  • Renderizador de Teste React (React Test Renderer)
  • Renderizador Superficial React (React Shallow Renderer)

Observe que para utilizar Hooks, todos os pacotes do React precisam estar na versão 16.8.0 ou superior. Hooks não irão funcionar se você esquecer de atualizar, por exemplo, o React DOM.

O React Native terá suporte ao Hooks na versão 0.59.

Suporte de Ferramentas

React Hooks agora são suportados pelo React DevTools. Assim como, as últimas definições de Flow e TypeScript do React. Nós recomendamos fortemente a utilização da nova regra lint, chamada: eslint-plugin-react-hooks, para a aplicação das melhores práticas de codificação com Hooks. Em breve, ela será incluída ao Create React App por padrão.

O Que Vem a Seguir

Nós descrevemos nossos planos para os próximos meses na recente publicação do Roteiro React.

Observe que React Hooks ainda não cobrem todos os casos de uso de classes, mas eles estão bem próximos. Atualmente, apenas os métodos que não possuem API de Hooks equivalentes são getSnapshotBeforeUpdate() e componentDidCatch(), estes ciclos de vida são relativamentes incomuns. Se você quiser, você deve conseguir utilizar Hooks em grande parte do novo código qual você está escrevendo.

Mesmo enquanto Hooks estavam em sua versão alpha, a comunidade React criou muitos exemplos e indicações interessantes usando Hooks, seja para animações, formulários, subscriptions, integração com outras bibliotecas e assim por diante. Nós estamos entusiasmados com Hooks, porque eles tornam a reutilização de código mais fácil, ajudando você a escrever seus componentes de forma simples e criando grandes experiências de usuário. Não podemos esperar para ver o que você irá criar em seguida!

Testando os Hooks

Nós adicionamos uma nova API nesta versão, chamada ReactTestUtils.act(). Ela garante que o comportamento de seus testes, correspondam de forma mais semelhante com o que acontece no navegador. Nós recomendamos encapsular quaquer código de renderização e execução de atualizações ao seu componente, dentro das chamadas aos métodos act(). Bibliotecas de teste, do mesmo modo, podem encapsular suas APIs com o método (por exemplo: utilitários do react-testing-library, como render e fireEvent, fazem isto).

Por exemplo, o exemplo de contador desta página pode ser testado assim:

import React from 'react';
import ReactDOM from 'react-dom';
import { act } from 'react-dom/test-utils';
import Counter from './Counter';

let container;

beforeEach(() => {
  container = document.createElement('div');
  document.body.appendChild(container);
});

afterEach(() => {
  document.body.removeChild(container);
  container = null;
});

it('can render and update a counter', () => {
  // Testa primeira renderização e resultado
  act(() => {
    ReactDOM.render(<Counter />, container);
  });
  const button = container.querySelector('button');
  const label = container.querySelector('p');
  expect(label.textContent).toBe('Você clicou 0 vezes');
  expect(document.title).toBe('Você clicou 0 vezes');

  // Testa segunda renderização e resultado
  act(() => {
    button.dispatchEvent(new MouseEvent('click', {bubbles: true}));
  });
  expect(label.textContent).toBe('Você clicou 1 vezes');
  expect(document.title).toBe('Você clicou 1 vezes');
});

As chamadas ao método act() também irão disparar os efeitos dentro delas.

Se você precisa testar um Hook customizado, você pode fazer isso criando um componente em seu teste e utilizar seu Hook a partir dele. Assim, você pode testar o componente qual você escreveu.

Para reduzir a repetição, nós recomendamos utilizar a react-testing-library, qual é projetada para incentivar a escrita de testes, que utilizam de seus componentes como o usuário final utiliza.

Agradecimento

Nós gostaríamos de agradecer todos aqueles que comentaram no Hooks RFC, por terem compartilhado suas opiniões. Nós lemos todos os seus comentários e fizemos alguns ajustes finais nas APIs baseando-se neles.

Instalação

React

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

Para instalar o React 16 com o Yarn, execute:

yarn add react@^16.8.0 react-dom@^16.8.0

Para instalar o React 16 com o npm, execute:

npm install --save react@^16.8.0 react-dom@^16.8.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 de instalações detalhadas.

Extensão ESLint para o React Hooks

Observação

Como mencionado acima, nós recomendamos severamente o uso da regra do eslint-plugin-react-hooks.

Se você está usando o Create React App, ao invéz da configuração manual do ESLint, você pode aguardar pela próxima versão do react-scrips, qual será lançada em breve e irá incluir esta regra.

Assumindo que você já possui o ESLint instalado, excute:

# npm
npm install eslint-plugin-react-hooks --save-dev

# yarn
yarn add eslint-plugin-react-hooks --dev

Então adicione em suas confugações do ESLint:

{
  "plugins": [
    // ...
    "react-hooks"
  ],
  "rules": {
    // ...
    "react-hooks/rules-of-hooks": "error"
  }
}

Histórico de Mudanças

React

  • Adiciona Hooks — uma forma de utilizar estado e outras funcionalidades do React sem escrever uma classe. (@acdlite et al. em #13968)
  • Aperfeiçoamento da API de inicialização lenta (lazy initialization) do Hook useReducer. (@acdlite em #14723)

React DOM

  • Evita renderização de valores identicos nos Hooks useState e useReducer. (@acdlite em #14569)
  • Não compare o primeiro argumento passado aos Hooks useEffect/useMemo/useCallback. (@acdlite em #14594)
  • Utilização do algortimo Object.is para comparação dos valores de useState e useReducer. (@Jessidhia em #14752)
  • Suporte síncrono aos thenables passados para React.lazy(). (@gaearon em #14626)
  • Renderiza os componentes com Hooks duas vezes no Modo Estrito (Strict Mode) - apenas DEV, para combinar o comportamento de classe. (@gaearon em #14654)
  • Aviso sobre a incompatibilidade do Hooks quanto ao desenvolvimento. (@threepointone em #14585 e @acdlite em #14591)
  • As funções de limpeza de resultados devem retornar undefined ou uma função. Todos os outros valores, incluindo null, não são permitidos. @acdlite em #14119

Renderizador de Teste React

  • Suporte para Hooks no renderizador superficial (Shallow Renderer). (@trueadm em #14567)
  • Correção do estado do shouldComponentUpdate junto ao getDerivedStateFromProps ao renderizador superficial (Shallow Renderer). (@chenesan em #14613)
  • Adiciona ReactTestRenderer.act() e ReactTestUtils.act() para atualizações em lote a fim de que testes sejam executados de forma mais semelhante ao comportamento real. (@threepointone em #14744)

Extensão ESLint: React Hooks

Histórico de mudanças do Hooks desde a versão alpha

O histórico de mudanças acima contém todas as mudanças notáveis, desde a nossa última versão estável (16.7.0). Assim como, todos o nossos lançamentos secundários, não interrompe a compatibilidade com as versões anteriores.

Se você está utilizando Hooks da versão alpha do React, observe que esta versão contêm algumas pequenas mudanças, que causa instabilidade ao Hooks. Nós não recomendamos a dependência da versão alpha em código de produção. Nós publicamos versões alpha para realizar mudanças com base na opinião da comunidade, antes da versão estável da API.

Aqui estão todas as mudanças radicais do Hooks, quais foram feitas desde a primeira versão alpha:

  • Remove useMutationEffect. (@sophiebits em #14336)
  • Renomeia useImperativeMethods para useImperativeHandle. (@threepointone em #14565)
  • Evita renderização de valores idênticos nos Hooks useState e useReducer. (@acdlite em #14569)
  • Não compare o primeiro argumento passado aos Hooks useEffect/useMemo/useCallback. (@acdlite em #14594)
  • Utilização do algortimo Object.is para comparação dos valores de useState e useReducer. (@Jessidhia em #14752)
  • Renderiza os componentes com Hooks duas vezes no Modo Estrito (Strict Mode) - apenas DEV. (@gaearon em #14654)
  • Aperfeiçoamento da API de inicialização lenta (lazy initialization) do Hook useReducer. (@acdlite em #14723)