Desmistificando React Hooks — useCallback
Começando
Se quiser acompanhar em seu IDE local, você pode encontrar o GitHub Repo aqui .
clonecd clientnpm inpm start
Igualdade Referencial é um conceito fundamental em JavaScript e Ciência da Computação como um todo. Então, vamos começar com uma demonstração dele em ação.
Incorporei capturas de tela ao longo do artigo para facilitar o uso em dispositivos móveis. Se você estiver na área de trabalho e o tiver clonado, execute referentialEquality.jspara observar a saída ou apenas jogue com o trecho JSFiddle incorporado abaixo.
Ao avaliar se o integer 1é estritamente igual ao integer 1, o console imprime true. Isso ocorre porque, bem… o integer 1 é estritamente igual ao integer 1.
Vemos o mesmo resultado ao avaliar duas strings.
Obviamente, este sempre será o caso para dois tipos de dados primitivos do mesmo valor.
Agora, e as estruturas de dados? Por exemplo, dois literais de objeto com os mesmos pares chave/valor? E os literais de objetos vazios?
Por que isso imprimiria false? Ao comparar se esses dois literais de objeto são estritamente iguais, o JavaScript usa seus respectivos endereços de memória .
Em outras palavras, esses dois objetos podem conter os mesmos valores , mas não estão referenciando o mesmo objeto . Eles parecem iguais, mas ocupam dois espaços diferentes na memória .
O mesmo se aplica se você estiver comparando dois literais de objeto, dois literais de matriz ou duas funções!
Para demonstrar isso melhor, definiremos uma função func, que retorna uma função anônima que, por sua vez, retorna outra coisa ( como um elemento JSX ).
Atribuiremos então duas funções diferentes, firstRendere secondRender, igual ao valor retornado por func.
Pense funccomo seu componente funcional React, enquanto firstRenderé uma função dentro dele na primeira renderização e secondRenderé uma função dentro dele na segunda renderização.
Mesmo que firstRendere secondRenderretornem o mesmo valor e sejam atribuídos a partir da mesma definição, eles não possuem igualdade referencial . Como resultado, toda vez que o componente renderiza, ele redefine essa função.
Infelizmente, em JavaScript, não é fácil imprimir esses endereços de memória como em Python, mas para uma explicação um pouco mais aprofundada de referência versus valor, dê uma olhada neste artigo do freeCodeCamp.
Este tópico pode ficar denso e você não precisa dar uma aula sobre ele esta noite. Então, por enquanto, lembre-se:
- tipo de dado primitivo
===tipo de dado primitivo - estrutura de dados
!==estrutura de dados.
Código inicial
Depois de ativar nosso aplicativo, abra o BookDetails.jsxcomponente e salve novamente. A primeira coisa que podemos notar em nosso servidor de desenvolvimento React é algo comum WARNINGque os jovens desenvolvedores tendem a ignorar. À medida que você atinge a força de trabalho e começa a escrever código para produção, seus linters serão ainda mais rígidos do que o que está embutido no create-react-app. WARNINGSirá virar para ERRORS, e alguns linters não permitirão que você empurre antes de endereçá-los ERRORS.
Portanto, em vez de ignorá-lo, vamos descobrir como tratá-lo.
NOTA: você pode primeiro precisar salvar novamente BookDetails.jsxpara criar esteWARNING
Se nos aprofundarmos no React Docs , podemos decodificar as soluções propostas semiconfusas para isso WARNINGda seguinte forma:
1. Inclua a definição da função dentro do arquivo useEffect.
- Não podemos chamar essa função em outro lugar, a menos que a redefinamos.
- Isso acionará
useEffecttoda vez que o estado ou os adereços mudarem, às vezes causando uma re-renderização infinita. E, em nosso caso, como estamos chamando nossa função de configurador de estado após uma chamada de API, isso pode sobrecarregar nossa API com infinitas solicitações de ponto de extremidade.
- A função não será chamada.
- Na primeira vez que o componente for renderizado, ele definirá nossa função, que acionará o
useEffect, o que fará com que o componente seja renderizado novamente, o que redefinirá a função, o que acionará ouseEffect, o que fará com que o componente seja renderizado novamente, o que irá redefinir a função…
A solução mais simples e preferida seria 'incluí-la', ou seja, mover a getBookDetailsdefinição da função para dentro do arquivo useEffect. Isso segue um princípio de Programação Orientada a Objetos conhecido como Encapsulamento .
Mas digamos que sabemos que precisamos chamar a função em outro lugar. Devemos redefini-lo mais tarde? Isso não é muito seco de nós.
Vamos alterar nosso array de dependências para incluir nossa referência de função. Agora você useEffectdeve ficar assim.
E getBookDetailspermanece definido acima do useEffect.
Agora temos um novoWARNING
Insira o gancho useCallback
Resumindo, o useCallbackgancho permite que você armazene em cache, ou 'memoize', uma função entre as re-renderizações do seu componente. Ele executa uma tarefa semelhante a useMemo, cujas nuances abordaremos em outro artigo.
Se o âmago da questão for do seu interesse, você pode ler mais nos documentos do React .
Observe o aviso:
Você só deve confiar useCallbackcomo uma otimização de desempenho. Se o seu código não funcionar sem ele, encontre o problema subjacente e corrija-o primeiro. Então você pode adicionar useCallbackpara melhorar o desempenho.
useCallbackSintaxe
useCallbackA sintaxe de ' é muito semelhante à useEffectsintaxe de ' que já conhecemos. Olhe para os esqueletos de cada um.
A pequena diferença é com useEffect, dizemos à função anônima para executar nossa função enquanto com useCallback, atribuímos o valor de retorno a uma referência a ser chamada em outro lugar.
Usando useCallback
Primeiro, vamos importar useCallbackde 'react'. Em vez de adicionar uma nova linha, é melhor desestruturar junto com nossas outras importações.
Agora podemos atribuir getBookDetailsao valor retornado de uma useCallbackchamada de função.
Em seguida, adicionamos toda a sintaxe para useCallback. Lembre-se de sua matriz de dependência!
Em nosso exemplo, precisamos asyncantes de nossos parâmetros.
E, finalmente, adicionamos a lógica de nossa função ao bloco de código.
Depois de salvar, obtemos ... outro arquivo WARNING.
Por que nosso array de dependências deve rastrear a idvariável?
Vamos pensar sobre isso.
- Se o valor de
idmudar,getBookDetailsprecisa atingir um ponto final diferente, então o React deve redefini-lo. A definição degetBookDetailsliteralmente depende do valor deid.
E por fim, é isso! Vemos verde em nosso servidor React dev. Um linter feliz é um desenvolvedor sênior feliz. E um Desenvolvedor Sênior feliz é um feliz você!
Estou sempre procurando novos amigos e colegas. Se você achou este artigo útil e gostaria de se conectar, você pode me encontrar em qualquer uma das minhas casas na web.
GitHub | Twitter | Linkedin | Local na rede Internet
Recursos
- Igualdade Referencial
- Tipos de dados primitivos de JavaScript vs. estruturas de dados
- Encapsulamento
useCallback- React Docs





































![O que é uma lista vinculada, afinal? [Parte 1]](https://post.nghiatu.com/assets/images/m/max/724/1*Xokk6XOjWyIGCBujkJsCzQ.jpeg)