Демистификация хуков React — useCallback

Dec 03 2022
В этой статье мы рассмотрим, когда и как использовать хук React useCallback, а также ошибки, допускаемые большинством младших разработчиков.
Приступая к работе Если вы хотите продолжить работу в локальной среде IDE, вы можете найти репозиторий GitHub здесь. Ссылочное равенство — это основополагающая концепция как в JavaScript, так и в компьютерных науках в целом.

Начиная

Если вы хотите продолжить работу в своей локальной среде IDE, вы можете найти репозиторий GitHub здесь .

  • clone
  • cd client
  • npm i
  • npm start

Ссылочное равенство — это основополагающая концепция как в JavaScript, так и в компьютерных науках в целом. Итак, начнем с демонстрации его в действии.

Я вставил скриншоты в статью для простоты использования на мобильных устройствах. Если вы находитесь на рабочем столе и клонировали его, запустите referentialEquality.js, чтобы посмотреть на результат, или просто поиграйте с фрагментом кода JSFiddle, встроенным ниже.

При оценке того, integer 1является ли строго равным integer 1, консоль выводит true. Это потому, что, ну… строго integer 1 равноinteger 1 .

целые числа строго равны

Мы видим тот же результат при оценке двух строк.

строки строго равны

Очевидно, что это всегда будет иметь место для двух примитивных типов данных с одним и тем же значением.

А как насчет структур данных? Например, два литерала объекта с одинаковыми парами ключ/значение? Как насчет литералов пустых объектов?

объекты не строго равны

Зачем это печатать false? При сравнении этих двух литералов объекта строго равны, JavaScript использует их соответствующие адреса памяти .

Другими словами, эти два объекта могут содержать одни и те же значения , но они не ссылаются на один и тот же объект . Они выглядят одинаково, но занимают два разных места в памяти .

То же самое применимо независимо от того, сравниваете ли вы два литерала объекта, два литерала массива или две функции!

массивы не строго равны

Чтобы продемонстрировать это дальше, мы определим функцию func, которая возвращает анонимную функцию, которая, в свою очередь, возвращает что-то еще ( например, элемент JSX ).

создание условного функционального компонента

Затем мы назначим две разные функции firstRenderи , secondRenderравные значению, возвращаемому функцией func.

назначение наших определений функций

Думайте о funcсвоем функциональном компоненте React, в то время как firstRenderэто функция внутри него при первом рендеринге и secondRenderфункция внутри него при втором рендеринге.

Несмотря на то, что firstRenderи secondRenderвозвращают одно и то же значение и присваиваются из одного и того же определения, они не имеют ссылочного равенства . В результате каждый раз, когда компонент отрисовывается, он переопределяет эту функцию.

наши две функции не строго равны

К сожалению, в JavaScript не так просто напечатать эти адреса памяти, как в Python, но более подробное объяснение ссылки и значения можно найти в этой статье на сайте freeCodeCamp.

Эта тема может стать сложной, и вам не нужно вести по ней класс сегодня вечером. Итак, пока просто запомните:

  • примитивный тип данных ===примитивный тип данных
  • структура данных !==структура данных.

Стартовый код

После того, как мы раскрутим наше приложение, откройте BookDetails.jsxкомпонент и сохраните его заново. Первое, что мы можем заметить на нашем сервере разработки React, — это то WARNING, что молодые разработчики склонны игнорировать. Когда вы наберетесь рабочей силы и начнете писать код для производства, ваши линтеры будут еще более строгими, чем то, что встроено в create-react-app. WARNINGSобратятся к ERRORS, а некоторые линтеры не позволят вам нажать перед тем, как вы обратитесь к этим ERRORS.

Поэтому вместо того, чтобы игнорировать это, давайте выясним, как с этим бороться.

Предлагаемые решения React

ПРИМЕЧАНИЕ. Сначала вам может потребоваться повторное сохранение BookDetails.jsx, чтобы создать этотWARNING

Если мы покопаемся в React Docs , мы сможем расшифровать полузапутанные предлагаемые решения следующим образом WARNING:

1. Включите определение функции в файл useEffect.

  • Мы не можем вызывать эту функцию в другом месте, пока не переопределим ее.
  • Это вызовет useEffect постоянное изменение состояния или реквизита, иногда вызывая бесконечный повторный рендеринг. И в нашем случае, поскольку мы вызываем нашу функцию установки состояния после вызова API, это может перегрузить наш API бесконечными запросами конечной точки.
  • Функция не будет вызываться.
  • При первом рендеринге компонента он определит нашу функцию, которая вызовет useEffect, что приведет к повторному рендерингу компонента, что переопределит функцию, которая вызовет useEffect, что приведет к повторному рендерингу компонента, что переопределит функцию…

Самым простым и предпочтительным решением было бы «включить его», то есть переместить getBookDetailsопределение функции внутрь файла useEffect. Это соответствует принципу объектно-ориентированного программирования, известному как инкапсуляция .

Но допустим, мы знаем, что нам нужно вызвать функцию в другом месте. Должны ли мы переопределить его позже? Это не очень СУХО с нашей стороны.

Давайте изменим наш массив зависимостей, чтобы включить ссылку на нашу функцию. Теперь вы useEffectдолжны выглядеть так.

включая нашу функцию в массив зависимостей

И getBookDetailsостается определенным над .useEffect

исходное определение нашей функции

Теперь у нас есть новыйWARNING

определение нашей функции вне useEffect при включении ее в массив зависимостей вызовет бесконечный повторный рендеринг

Введите хук useCallback

Короче говоря, useCallbackхук позволяет вам кэшировать или «запоминать» функцию между повторными рендерингами вашего компонента. Он выполняет ту же задачу useMemo, что и , нюансы которой мы рассмотрим в другой статье.

Если вас интересуют подробности этого, вы можете прочитать больше в документации React .

Обратите внимание на их предупреждение:

Вы должны полагаться только useCallbackна оптимизацию производительности. Если ваш код не работает без него, сначала найдите основную проблему и устраните ее. Затем вы можете добавить useCallback, чтобы улучшить производительность.

useCallbackСинтаксис

useCallbackСинтаксис 's очень похож на useEffectсинтаксис '', который мы уже знаем. Посмотрите на скелеты каждого.

два хука имеют идентичные синтаксические скелеты

Небольшая разница заключается в том useEffect, что с помощью мы сообщаем анонимной функции о выполнении нашей функции , а с помощью useCallbackмы присваиваем возвращаемое значение ссылке, которая будет вызываться в другом месте.

Использование обратного вызова

Во-первых, мы будем импортировать useCallbackиз 'react'. Вместо того, чтобы добавлять новую строку, лучше удалить ее вместе с другими импортируемыми данными.

элементы, деструктурированные из одного и того же пакета, лучше всего импортировать в одну строку

Теперь мы можем присвоить getBookDetailsзначение, возвращаемое useCallbackвызовом функции.

назначить возврат useCallback нашей ссылке

Затем мы добавляем весь синтаксис для useCallback. Помните свой массив зависимостей!

заполните скелет обратного звонка

В нашем примере нам нужно asyncперед нашими параметрами.

добавить асинхронный

И, наконец, мы добавляем логику нашей функции в блок кода.

добавим нашу логику в блок кода useCallback

Как только мы сохраним, мы получим… еще один WARNING.

Возврат useCallback зависит от значения id

Почему наш массив зависимостей должен отслеживать idпеременную?

Давайте обдумаем это.

  • Если значение idизменяется, getBookDetailsнеобходимо попасть в другую конечную точку, поэтому React должен переопределить ее. Определение getBookDetailsбуквально зависит от значения id.
готовые варианты обоих крючков

И, наконец, это все! Мы видим зеленый цвет на нашем сервере разработки React. Счастливый линтер — это счастливый старший разработчик. А счастливый Senior Developer — это счастливый ты!

Я всегда ищу новых друзей и коллег. Если вы нашли эту статью полезной и хотели бы связаться, вы можете найти меня в любом из моих домов в Интернете.

Гитхаб | Твиттер | Линкедин | Веб-сайт

Ресурсы

  • Ссылочное равенство
  • Примитивные типы данных JavaScript и структуры данных
  • Инкапсуляция
  • useCallback
  • Реагировать Документы