Изучите основ React Hooks(Крючки) за <10 минут

В начале этого года команда React выпустила новое дополнение — хуки для React в версии 16.8.0.

Если бы React была большой миской конфет, то крючки — это последнее дополнение, очень жевательные конфеты с отличным вкусом!

Итак, что именно означают крючки? И почему они стоят вашего времени?

Вступление

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

В более долгосрочной перспективе мы ожидаем, что хуки будут основным способом написания компонентов React — React Team

Если крючки так важны, почему бы не узнать о них в увлекательной игровой форме!

Конфетница

Считайте React красивой миской конфет.

Миска конфет была невероятно полезна людям во всем мире.

Люди, которые сделали эту миску конфет, поняли, что некоторые конфеты в миске не приносили людям много пользы.

Да, пара конфет была очень вкусной! Но они привели к некоторой сложности, когда люди ели их — подумайте, реквизит рендера и компоненты более высокого порядка(render props and higher order components)?

Они сделали правильную вещь — не выбрасывая все предыдущие конфеты, но делая новые наборы конфет.

Эти конфеты назывались Крючками(Hooks).

Эти конфеты существуют для одной цели: чтобы вам было легче делать то, что вы уже делали.

Эти конфеты не супер особенные. На самом деле, когда вы начнете есть их, вы поймете, что они на вкус знакомы — это всего лишь функции Javascript!

Как и у всех хороших конфет, у этих 10 новых конфет есть свои уникальные названия. Хотя они все вместе называются крючками.

Их имена всегда начинаются с трехбуквенного слова use … e.g. useState, useEffect etc.

Эти 10 конфет, как и шоколад, содержат одни и те же ингредиенты. Знание того, как один вкус, помогает вам относиться к другому.

Звучит смешно? Теперь давайте возьмем эти конфеты.

Состояние крючков(The State Hook)

Как было сказано ранее, хуки — это функции. Официально их 10. 10 новых функций, которые делают функции записи и обмена в ваших компонентах намного более выразительными.

Первый хук, на который мы взглянем, называется:useState.

В течение долгого времени вы не могли использовать локальное состояние в функциональном компоненте. Ну не до крючков.

С useState, Ваш функциональный компонент может иметь (и обновлять) локальное состояние.

Как интересно.

Рассмотрим следующее встречное приложение:

С компонентом Counter, показанным ниже:

Легко ???

Позвольте мне задать вам один простой вопрос. Почему именно у нас есть этот компонент как компонент класса?

Ответ прост, потому что нам нужно отслеживать некоторые локальные состояния внутри компонента.

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

Чем отличается?

Я проведу вас через это шаг за шагом.

Функциональный компонент не имеет всего синтаксиса Расширения класса …

function CounterHooks() {

}

Также не требуется метод рендеринга.

function CounterHooks() {

return (
<div>
<h3 className="center">Welcome to the Counter of Life </h3>
<button
className="center-block"
onClick={this.handleClick}> {count} </button>
</div>
);
}

Есть две проблемы с кодом выше.

  1. Вы не должны использовать ключевое слово this в компонентах функций.
  2. Переменная состояния сount не была определена.

Извлечь handleClick Нажмите на отдельную функцию внутри функционального компонента:

function CounterHooks() {
const handleClick = () => {

}
return (
<div>
<h3 className="center">Welcome to the Counter of Life </h3>
<button
className="center-block"
onClick={handleClick}> {count} </button>
</div>
);
}

До рефакторинга переменная count была получена из объекта состояния компонента класса.

В функциональных компонентах и с хуками это происходит из-за вызова функции useState или хука.

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

Вызов этой функции возвращает массив с двумя значениями.

//🦄 returns an array with 2 values. 
useState(0)

Первое значение — это отслеживаемое значение текущего состояния, а второе — функция для обновления значения состояния.

Думайте об этом как о некотором state и реплике setState — однако они не совсем одинаковы.

С этим новым знанием, здесь используется useState в действий.

function CounterHooks() {
// 🦄
const [count, setCount] = useState(0);

const handleClick = () => {
setCount(count + 1)
}

return (
<div>
<h3 className="center">Welcome to the Counter of Life </h3>
<button
className="center-block"
onClick={handleClick}> {count} </button>
</div>
);
}

Здесь следует отметить несколько вещей, помимо очевидной простоты кода!

Во-первых, поскольку вызов useState возвращает массив значений, значения можно легко разбить на отдельные значения, как показано ниже:

const [count, setCount] = useState(0);

Также обратите внимание, что функция handleClick в рефакторированном коде не нуждается в какой-либо ссылке на prevState или что-то подобное.

Он просто вызывает setCount с новым значением count + 1.

const handleClick = () => {
setCount(count + 1)
}

Это связано с тем, что правильное значение переменной состояния count всегда будет сохраняться при повторном рендеринге.

Итак, нужно обновить переменную состояния счета, просто вызовите setCount с новым значением, например setCount (count + 1)

Как бы просто это ни звучало, вы создали свой самый первый компонент с использованием хуков. Я знаю, что это надуманный пример, но это хорошее начало!

Несколько вызовов useState

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

// single property 
state = {
count: 0
}

// multiple properties
state = {
count: 0,
time: '07:00'
}

С useState вы могли заметить небольшую разницу.

В приведенном выше примере мы только вызывали useState с фактическим начальным значением. Не объект для хранения значения.

useState(0)

Итак, что, если мы хотим получить другое значение состояния

Можно ли использовать несколько вызовов useState?

Рассмотрим компонент ниже. То же, что и раньше, но на этот раз он отслеживает время нажатия.

Как вы можете видеть, использование хуков совершенно одинаково, за исключением нового вызова useState.

const [time, setTime] = useState(new Date())

Теперь время используется в визуализированном JSX для получения часа, минуты и секунды щелчка.

<p className="center"> 
at: { `${time.getHours()} : ${time.getMinutes()} : ${time.getSeconds()}`}
</p>

Классно!

Однако возможно ли использовать объект с useState в отличие от нескольких вызовов useState?

Абсолютно!

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

Эффект Крюк

С компонентами класса вы, вероятно, выполняете побочные эффекты, такие как ведение журнала, выборка данных или управление подписками.

Эти побочные эффекты можно кратко назвать «эффектами», и для этой цели был создан хук эффекта useEffect.

Как это используется?

Хук useEffect вызывается передачей ему функции, в рамках которой вы можете выполнять свои побочные эффекты.

Вот быстрый пример.

useEffect(() => {
// 🐢 you can perform side effects here
console.log("useEffect first timer here.")
})

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

Следующий логический вопрос: когда вызывается функция useEffect?

Хорошо, помните, что в компонентах класса у вас были методы жизненного цикла, такие как componentDidMount и componentDidUpdate.

Поскольку функциональные компоненты не имеют этих методов жизненного цикла, useEffect вроде бы занимает их место.

Таким образом, в приведенном выше примере функция внутри useEffect, также известная как функция эффекта, будет вызываться при монтировании функционального компонента (componentDidMount) и при обновлении компонента componentDidUpdate).

Вот это в действии.

Добавив приведенный выше вызов useEffect в приложение counter, мы получаем следующее поведение.

Примечание: хук useEffect не полностью совпадает с компонентом componentDidMount + componentDidUpdate. Это можно рассматривать как таковое, но реализация отличается некоторыми тонкими различиями.

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

Что если вы хотите запускать функцию эффекта только при монтировании компонента?

Это частый случай использования, когда useEffect принимает второй параметр — массив зависимостей для обработки этого.

Если вы передаете пустой массив, функция эффекта запускается только при монтировании — последующие повторные рендеринг не вызывают функцию эффекта.

useEffect(() => {
console.log("useEffect first timer here.")
}, [])

Если вы передадите какие-либо значения в этот массив, то функция эффекта будет запущена при монтировании, и в любое время переданные значения будут обновлены. Т.е. если любое из значений будет изменено, выполненный вызов будет перезапущен.

useEffect(() => {
console.log("useEffect first timer here.")
}, [count])

Функция эффекта будет запускаться при монтировании и при каждом изменении функции счета.

А как насчет подписок?

В определенных приложениях можно подписаться и отписаться от определенных эффектов.

Учтите следующее:

useEffect(() => {
const clicked = () => console.log('window clicked');
window.addEventListener('click', clicked);
}, [])

В приведенном выше эффекте при монтировании к окну прикрепляется прослушиватель событий щелчка.

Как мы отписываемся от этого слушателя, когда компонент отключен?

Что ж, useEffect позволяет это сделать.

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

useEffect(() => {
const clicked = () => console.log('window clicked');
window.addEventListener('click', clicked);

return () => {
window.removeEventListener('click', clicked)
}
}, [])

С помощью ловушки useEffect можно сделать гораздо больше, например, выполнять вызовы API.

Создайте свои собственные крючки

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

Тем не менее, React также предоставляет вам возможность сделать свои собственные уникальные конфеты — так называемые нестандартные зацепки.

Итак, как это работает?

Пользовательский хук это просто обычная функция. Однако его имя должно начинаться со слова use, и, если необходимо, оно может вызывать любой из крюков React внутри себя.

Ниже приведен пример:

Правила Крюков

Есть два правила, которых нужно придерживаться при использовании хуков.

  1. Только Call Hooks на верхнем уровне, то есть не в пределах условных, циклов или вложенных функций.
  2. Только вызовы из функций React, т. Е. Функциональных компонентов и пользовательских хуков.

Этот плагин ESLint отлично подходит для обеспечения соблюдения этих правил в ваших проектах.

Текст был взят и переведен Ohans Emmanuel.

Я публикую статьи о программировании и технологиях, надеюсь я смогу принести Вам ценность и помочь в достижении Ваших целей! Твитер. ФэйсБук.Вконтакте.

--

--

Iurii Kalashnikov
FreeCodeCamp Russia(Русскоязычный)

Программист, бразильское джиу джитсу. https://github.com/YKalashnikov давайте дружить