Começando com a API React Hooks

Publicados: 2022-03-10
Resumo rápido ↬ Neste tutorial, você aprenderá e entenderá o que são hooks React, os Hooks React básicos que estão disponíveis e também exemplos de como escrevê-los para suas aplicações React. No processo, você também conhecerá alguns hooks adicionais que foram enviados com o React 16.8 e também como escrever seus próprios Hooks React personalizados.

Quando o React 16.8 foi lançado oficialmente no início de fevereiro de 2019, ele foi enviado com uma API adicional que permite usar o estado e outros recursos no React sem escrever uma classe. Essa API adicional é chamada de Hooks e está se tornando popular no ecossistema React, desde projetos de código aberto até o uso em aplicativos de produção.

React Hooks são totalmente opt-in, o que significa que reescrever o código existente é desnecessário, eles não contêm nenhuma alteração importante e estão disponíveis para uso com o lançamento do React 16.8. Alguns desenvolvedores curiosos têm feito uso da API Hooks antes mesmo de ser lançada oficialmente, mas naquela época ela não era estável e era apenas um recurso experimental. Agora é estável e recomendado para os desenvolvedores do React usarem.

Nota : Não falaremos sobre React ou JavaScript em geral. Um bom conhecimento de ReactJS e JavaScript será útil enquanto você trabalha neste tutorial.

O que são Hooks React?

React Hooks são funções embutidas que permitem que desenvolvedores React usem métodos de estado e ciclo de vida dentro de componentes funcionais, eles também trabalham em conjunto com o código existente, para que possam ser facilmente adotados em uma base de código. A maneira como os Hooks foram apresentados ao público foi que eles permitem que os desenvolvedores usem o estado em componentes funcionais, mas sob o capô, os Hooks são muito mais poderosos do que isso. Eles permitem que os desenvolvedores do React aproveitem os seguintes benefícios:

  • Reutilização de código aprimorada;
  • Melhor composição de código;
  • Melhores padrões;
  • Compartilhamento de lógica não visual com o uso de ganchos personalizados;
  • Flexibilidade na movimentação para cima e para baixo na árvore de components .

Com o React Hooks, os desenvolvedores têm o poder de usar componentes funcionais para quase tudo o que precisam fazer, desde renderizar a interface do usuário até manipular o estado e também a lógica - o que é muito legal.

Motivação por trás do lançamento do React Hooks

De acordo com a documentação oficial do ReactJS, a seguir está a motivação por trás do lançamento do React Hooks:

  • Reutilizar a lógica com estado entre componentes é difícil.
    Com Hooks, você pode reutilizar a lógica entre seus componentes sem alterar sua arquitetura ou estrutura.
  • Componentes complexos podem ser difíceis de entender.
    Quando os componentes se tornam maiores e realizam muitas operações, torna-se difícil de entender a longo prazo. Os ganchos resolvem isso permitindo que você separe um componente único específico em várias funções menores com base em quais partes desse componente separado estão relacionadas (como configurar uma assinatura ou buscar dados), em vez de ter que forçar uma divisão com base nos métodos do ciclo de vida.
  • As aulas são bastante confusas.
    As aulas são um obstáculo para aprender React corretamente; você precisaria entender como this funciona em JavaScript, que difere de outras linguagens. O React Hooks resolve esse problema permitindo que os desenvolvedores usem os melhores recursos do React sem precisar usar classes.
Mais depois do salto! Continue lendo abaixo ↓

As regras dos ganchos

Existem duas regras principais que devem ser rigorosamente seguidas, conforme declarado pela equipe principal do React, descritas na documentação da proposta de ganchos.

  • Certifique-se de não usar Hooks dentro de loops, condições ou funções aninhadas;
  • Use apenas Hooks de dentro de React Functions.

Ganchos de reação básicos

Existem 10 hooks embutidos que foram enviados com o React 16.8, mas os hooks básicos (comumente usados) incluem:

  • useState()
  • useEffect()
  • useContext()
  • useReducer()

Estes são os 4 ganchos básicos que são comumente usados ​​por desenvolvedores React que adotaram React Hooks em suas bases de código.

useState()

O gancho useState() permite que os desenvolvedores do React atualizem, manipulem e manipulem o estado dentro de componentes funcionais sem precisar convertê-lo em um componente de classe. Vamos usar o trecho de código abaixo é um componente simples de contador de idade e o usaremos para explicar o poder e a sintaxe do gancho useState() .

 function App() { const [age, setAge] = useState(19); const handleClick = () => setAge(age + 1) return <div> I am {age} Years Old <div> <button onClick={handleClick}>Increase my age! </button> </div> </div> }

Se você notou, nosso componente parece bem simples, conciso e agora é um componente funcional e também não tem o nível de complexidade que um componente de classe teria.

O useState() recebe um estado inicial como argumento e então retorna, fazendo uso da desestruturação de array em JavaScript, as duas variáveis ​​no array podem ser nomeadas what. A primeira variável é o estado real, enquanto a segunda variável é uma função destinada a atualizar o estado fornecendo um novo estado.

Nosso aplicativo React finalizado (visualização grande)

É assim que nosso componente deve ficar quando renderizado em nosso aplicativo React. Ao clicar no botão “Aumentar minha idade”, o estado da idade mudará e o componente funcionará como um componente de classe com estado.

useEffect()

O gancho useEffect() aceita uma função que contém código eficaz. Em componentes funcionais, efeitos como mutações, assinaturas, temporizadores, registro e outros efeitos não podem ser colocados dentro de um componente funcional porque isso levaria a muitas inconsistências quando a interface do usuário é renderizada e também a erros confusos.

Ao usar o gancho useEffect() , a função effectual passada para ele será executada logo após a exibição da renderização na tela. Os efeitos são basicamente espreitados na forma imperativa de construir UIs que é bem diferente da forma funcional do React.

Por padrão, os efeitos são executados principalmente após a conclusão da renderização, mas você tem a opção de ativá-los também quando certos valores são alterados.

O gancho useEffect() é usado principalmente para efeitos colaterais que geralmente são usados ​​para interações com a API Browser/DOM ​​ou busca de dados ou assinaturas semelhantes a APIs externas. Além disso, se você já estiver familiarizado com o funcionamento dos métodos de ciclo de vida React, você também pode pensar no gancho useEffect() como montagem , atualização e desmontagem de componentes — tudo combinado em uma função. Ele nos permite replicar os métodos do ciclo de vida em componentes funcionais.

Usaremos os trechos de código abaixo para explicar a maneira mais básica possível usando o gancho useEffect() .

Etapa 1: defina o estado do seu aplicativo

 import React, {useState} from 'react'; function App() { //Define State const [name, setName] = useState({firstName: 'name', surname: 'surname'}); const [title, setTitle] = useState('BIO'); return( <div> <h1>Title: {title}</h1> <h3>Name: {name.firstName}</h3> <h3>Surname: {name.surname}</h3> </div> ); }; export default App

Assim como discutimos na seção anterior sobre como usar o gancho useState() para manipular o estado dentro dos componentes funcionais, nós o usamos em nosso trecho de código para definir o estado do nosso aplicativo que renderiza meu nome completo.

Etapa 2: chame o gancho useEffect

 import React, {useState, useEffect} from 'react'; function App() { //Define State const [name, setName] = useState({firstName: 'name', surname: 'surname'}); const [title, setTitle] = useState('BIO'); //Call the use effect hook useEffect(() => { setName({FirstName: 'Shedrack', surname: 'Akintayo'}) }, [])//pass in an empty array as a second argument return( <div> <h1>Title: {title}</h1> <h3>Name: {name.firstName}</h3> <h3>Surname: {name.surname}</h3> </div> ); }; export default App

Agora importamos o gancho useEffect e também usamos a função useEffect() para definir o estado de nossa propriedade name e surname, que é bastante organizada e concisa.

Você deve ter notado o gancho useEffect no segundo argumento que é um array vazio; isso ocorre porque contém uma chamada para o setFullName que não possui uma lista de dependências. Passar o segundo argumento evitará uma cadeia infinita de atualizações ( componentDidUpdate() ) e também permitirá que nosso useEffect() atue como um método de ciclo de vida componentDidMount e renderize uma vez sem renderizar novamente a cada alteração na árvore.

Nosso aplicativo React agora deve ficar assim:

Reagir aplicativo usando o gancho useEffect (visualização grande)

Também podemos usar alterar a propriedade title do nosso aplicativo dentro da função useEffect() chamando a função setTitle() , assim:

 import React, {useState, useEffect} from 'react'; function App() { //Define State const [name, setName] = useState({firstName: 'name', surname: 'surname'}); const [title, setTitle] = useState('BIO'); //Call the use effect hook useEffect(() => { setName({firstName: 'Shedrack', surname: 'Akintayo'}) setTitle({'My Full Name'}) //Set Title }, [])// pass in an empty array as a second argument return( <div> <h1>Title: {title}</h1> <h3>Name: {name.firstName}</h3> <h3>Surname: {name.surname}</h3> </div> ); }; export default App

Agora, depois que nosso aplicativo foi renderizado novamente, ele agora mostra o novo título.

Nosso projeto finalizado (Visualização grande)

useContext()

O gancho useContext() aceita um objeto de contexto, ou seja, o valor que é retornado de React.createContext e, em seguida, retorna o valor de contexto atual para esse contexto.

Este gancho fornece aos componentes funcionais acesso fácil ao contexto do seu aplicativo React. Antes que o gancho useContext fosse introduzido, você precisaria configurar um contextType ou um <Consumer> para acessar seu estado global passado de algum provedor em um componente de classe.

Basicamente, o gancho useContext funciona com a API React Context, que é uma maneira de compartilhar dados profundamente em todo o seu aplicativo sem a necessidade de passar manualmente os adereços do seu aplicativo por vários níveis. Agora, o useContext() torna o uso de Context um pouco mais fácil.

Os trechos de código abaixo mostrarão como a Context API funciona e como o useContext Hook a torna melhor.

A maneira normal de usar a API de contexto

 import React from "react"; import ReactDOM from "react-dom"; const NumberContext = React.createContext(); function App() { return ( <NumberContext.Provider value={45}> <div> <Display /> </div> </NumberContext.Provider> ); } function Display() { return ( <NumberContext.Consumer> {value => <div>The answer to the question is {value}.</div>} </NumberContext.Consumer> ); } ReactDOM.render(<App />, document.querySelector("#root"));

Vamos agora dividir o trecho de código e explicar cada conceito.

Abaixo, estamos criando um contexto chamado NumberContext . Destina-se a retornar um objeto com dois valores: { Provider, Consumer } .

 const NumberContext = React.createContext();

Em seguida, usamos o valor Provider que foi retornado do NumberContext que criamos para disponibilizar um valor específico para todos os filhos.

 function App() { return ( <NumberContext.Provider value={45}> <div> <Display /> </div> </NumberContext.Provider> ); }

Com isso, podemos usar o valor Consumer que foi retornado do NumberContext que criamos para obter o valor que disponibilizamos para todos os filhos. Se você notou, este componente não recebeu nenhum adereço.

 function Display() { return ( <NumberContext.Consumer> {value => <div>The answer to the question is {value}.</div>} </NumberContext.Consumer> ); } ReactDOM.render(<App />, document.querySelector("#root"));

Observe como conseguimos obter o valor do componente App no ​​componente Display envolvendo nosso conteúdo em um NumberContext.Consumer e usando o método render props para recuperar o valor e renderizá-lo.

Tudo funciona bem e o método render props que usamos é um padrão muito bom para lidar com dados dinâmicos, mas a longo prazo, ele introduz alguns aninhamentos desnecessários e confusão se você não estiver acostumado.

Usando o método useContext

Para explicar o método useContext vamos reescrever o componente Display usando o gancho useContext.

 // import useContext (or we could write React.useContext) import React, { useContext } from 'react'; // old code goes here function Display() { const value = useContext(NumberContext); return <div>The answer is {value}.</div>; }

Isso é tudo que precisamos fazer para mostrar nosso valor. Bem legal, certo? Você chama o gancho useContext() e passa o objeto de contexto que criamos e pegamos o valor dele.

Nota: Não esqueça que o argumento que é passado para o gancho useContext deve ser o próprio objeto de contexto e qualquer componente que chame o useContext sempre será renderizado novamente quando o valor do contexto for alterado.

useReducer()

O gancho useReducer é usado para lidar com estados complexos e transições de estado. Ele recebe uma função reducer e também uma entrada de estado inicial; em seguida, ele retorna o estado atual e também uma função de dispatch como saída por meio da desestruturação de array.

O código abaixo é a sintaxe adequada para usar o gancho useReducer .

 const [state, dispatch] = useReducer(reducer, initialArg, init);

É uma espécie de alternativa ao gancho useState ; geralmente é preferível useState quando você tem lógica de estado complexa que tem a ver com vários subvalores ou quando o próximo estado depende do anterior.

Outros ganchos de reação disponíveis

useCallback Esse gancho retorna uma função de retorno de chamada que é memorizada e que só muda se uma dependência na árvore de dependências for alterada.
useMemo Este hook retorna um valor memoizado, você pode passar uma função “create” e também um array de dependências. O valor que ele retorna só usará o valor memorizado novamente se uma das dependências na árvore de dependências for alterada.
useRef Este gancho retorna um objeto ref mutável cuja propriedade .current é inicializada para o argumento passado ( initialValue ). O objeto retornado estará disponível por toda a vida útil do componente.
useImperativeHandle Este gancho é usado para personalizar o valor da instância que é disponibilizado para componentes pai ao usar refs no React.
useLayoutEffect Esse gancho é semelhante ao gancho useEffect , no entanto, ele é acionado de forma síncrona após todas as mutações do DOM. Ele também renderiza da mesma maneira que componentDidUpdate e componentDidMount .
useDebugValue Este gancho pode ser usado para exibir um rótulo para ganchos personalizados no React Dev Tools. É muito útil para depurar com o React Dev Tools.

Ganchos de reação personalizados

Um “gancho customizado” é uma função JavaScript cujos nomes são prefixados com a palavra use e podem ser usados ​​para chamar outros Ganchos. Também permite extrair a lógica do componente em funções reutilizáveis; são funções JavaScript normais que podem fazer uso de outros Hooks dentro dele e também contêm uma lógica stateful comum que pode ser usada em vários componentes.

Os trechos de código abaixo demonstram um exemplo de um React Hook customizado para implementação de rolagem infinita (por Paulo Levy):

 import { useState } from "react"; export const useInfiniteScroll = (start = 30, pace = 10) => { const [limit, setLimit] = useState(start); window.onscroll = () => { if ( window.innerHeight + document.documentElement.scrollTop === document.documentElement.offsetHeight ) { setLimit(limit + pace); } }; return limit; };

Este Hook customizado aceita dois argumentos que são start e pace . O argumento start é o número inicial de elementos a serem renderizados, enquanto o argumento pace é o número subsequente de elementos a serem renderizados. Por padrão, os argumentos start e pace são definidos para 30 e 10 , respectivamente, o que significa que você pode realmente chamar o Hook sem nenhum argumento e esses valores padrão serão usados.

Então, para usar esse Hook dentro de um aplicativo React, nós o usaríamos com uma API online que retorna dados 'falsos':

 import React, { useState, useEffect } from "react"; import { useInfiniteScroll } from "./useInfiniteScroll"; const App = () => { let infiniteScroll = useInfiniteScroll(); const [tableContent, setTableContent] = useState([]); useEffect(() => { fetch("https://jsonplaceholder.typicode.com/todos/") .then(response => response.json()) .then(json => setTableContent(json)); }, []); return ( <div style={{ textAlign: "center" }}> <table> <thead> <tr> <th>User ID</th> <th>Title</th> </tr> </thead> <tbody> {tableContent.slice(0, infiniteScroll).map(content => { return ( <tr key={content.id}> <td style={{ paddingTop: "10px" }}>{content.userId}</td> <td style={{ paddingTop: "10px" }}>{content.title}</td> </tr> ); })} </tbody> </table> </div> ); }; export default App;

O código acima renderizará uma lista de dados falsos ( userID e title ) que fazem uso do gancho de rolagem infinita para exibir o número inicial de dados na tela.

Conclusão

Espero que você tenha gostado de trabalhar com este tutorial. Você sempre pode ler mais sobre React Hooks nas referências abaixo.

Se você tiver alguma dúvida, pode deixá-las na seção de comentários e ficarei feliz em responder a cada uma!

O repositório de suporte para este artigo está disponível no Github.

Recursos e leitura adicional

  • “Referência da API Hooks,” React.js Docs
  • “O que são React Hooks?”, Robin Wieruch
  • “Como funciona o gancho useContext ”, Dave Ceddia
  • “React Hooks: How To Use useEffect() ”, Hossein Ahmadi, Medium
  • “Escrevendo seus próprios ganchos de reação personalizados”, Aayush Jaiswal, Medium
  • “Receitas fáceis de entender do React Hook,” Gabe Ragland, useHooks()