Внедрение React Hooks коренным образом изменило то, как мы создаем React-приложения, раскрывая функции состояния и жизненного цикла, выходящие за рамки классовых компонентов. Функциональные компоненты теперь являются первоклассными жителями React, составляя основную часть React приложений.

Несмотря на то, что React Hooks невероятно мощные, их также легко использовать, внедряя неожиданное поведение или ошибки в свой код.

Давайте рассмотрим некоторые лучшие методы использования React Hooks, чтобы убедиться, что вы пишете чистый, эффективный и удобный в обслуживании код.

Используйте Hooks, так как они должны быть использованы.

Хотя это может показаться очевидным, я видел довольно вопиющее использование Hooks таким образом, что они не должны быть использованы. React определил следующие правила Hook.

Всегда вызывайте Hooks на верхнем уровне вашего кода

Не вызывайте Hooks внутри циклов, условий и вложенных функций. Рассмотрим пример:

if (setStorage) {
  useEffect(() => {
    localStorage.setItem('item', 'example');
  })
}

Обратите внимание, как useEffect вложен в утверждение if.

Условие If должно перейти в тело useEffect

useEffect(() => {
  if (setStorage) {
    localStorage.setItem('item', 'example');
  }
})

Это предотвращает появление странных ошибок от Hooks, которые не вызываются в одном и том же порядке каждый раз, когда компонент выводит и позволяет React должным образом сохранять состояние во всех вызовах useState и useEffect.

Используйте Hooks только в функциональных компонентах

Хотя это может показаться очевидным, не используйте React Hooks в обычном JS-коде — только в компонентах. Это облегчает отслеживание того, где вы модифицируете и поддерживаете состояние.

Есть плагин ESLint для React Hooks — Используйте его.

React выпустила отличный плагин ESLint под названием eslint-plugin-react-hooks, который помогает разработчикам правильно писать Hooks в своих проектах. Используйте этот плагин eslint, чтобы ловить и исправлять ошибки Hook еще до запуска вашего приложения.

Определены два относительно простых ESLint правила:

  • react-hooks/rules-of-hooks
  • react-hooks/exhaustive-deps

Первое правило просто приводит ваш код в соответствие с правилами Hooks, как объяснялось в последнем разделе. Второе правило гарантирует, что каждое значение, на которое ссылается внутри функции эффекта, находится внутри массива зависимостей.

Например, данный код выдаст исчерпывающее exhaustive-deps, так как он обращается к переменной componentId, которой нет в массиве зависимостей:

function Component({componentId}) {
  
  useEffect(() => {
    getComponent(componentId)
      .then((component) => console.log(component))
  }, []) // no `componentId` here!
}

Хотя это может показаться раздражающим, это поможет вам избежать некоторых странных ошибок, связанных с незарегистрированными зависимостями.

useState можно использовать с объектами тоже!

Многие примеры useState объявляют несколько состояний с несколькими переменными:

const [userEmail, setUserEmail] = useState('')
const [userName, setUserName] = useState('')
const [isError, setIsError] = useState(true)

Хотя это работает, это может быть немного многословно, когда вы начинаете иметь больше значений, которые поддерживаются в вашем локальном состоянии. useState также может содержать массивы и объекты в полном порядке, так почему бы не использовать его?

const [state, setState] = ({
  email: '[email protected]',
  userName: 'Name',
  isError: false,
})

Единственным предостережением здесь является то, что при настройке состояния на обновление одного значения объекта, вы должны убедиться, что вы правильно объединили старое состояние в новое:

setState((oldState) => ({
  ...oldState,
  userName: 'New Name',
}))

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

Помните, что рекомендуется разбивать состояние на несколько переменных состояний, на основе которых значения изменяются вместе с помощью React (в основном для удобочитаемости). Но для состояний, подобных формам, проще сгруппировать состояния вместе.

Пользовательские крючки — это круто!

По мере создания приложения React вы начнете замечать, что логика приложения распределена между многими компонентами.

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

Не используйте Prop Drilling

Prop drilling — распространенная проблема в React приложениях, где данные передаются вниз от одного родительского компонента через слои до тех пор, пока они не достигнут нужного дочернего компонента, в то время как некоторые вложенные компоненты на самом деле не используют их.

React Context — это способ передачи данных вниз по дереву компонентов без необходимости их передачи через дочерние компоненты, которые не используют их вручную. Значение React Context определяется родительским компонентом и может быть доступно в любом дочернем компоненте с помощью useContext Hook. Это отличный способ поддерживать глобальное состояние действительно просто. Взгляните на useContext Hook в документации.

Заключение

React Hook API невероятно мощный при правильном использовании. Если вы будете следовать лучшим практикам, вы убедитесь, что у вас есть код, не содержащий ошибок и поддерживаемый, с которым приятно работать.