Хукі дозволяють використовувати різні функції React з ваших компонентів. Ви можете використовувати вбудовані хуки або комбінувати їх для створення власних. На цій сторінці наведено всі вбудовані хуки в React. Стан дозволяє компоненту "запам'ятовувати" інформацію, наприклад, що вводиться користувачем. Наприклад, компонент форми може використовувати стан зберігання значення введення, а компонент галереї зображень - для зберігання індексу вибраного зображення. Щоб додати стан до компонента, використовуйте один із цих хуків: Контекст дозволяє компоненту отримувати інформацію від віддалених батьків, не передаючи її як пропсів. Наприклад, компонент верхнього рівня вашої програми може передавати поточну тему інтерфейсу користувача всім компонентам нижче, незалежно від глибини. Рефи дозволяють компоненту зберігати деяку інформацію, яка не використовується для рендерингу, наприклад, вузол DOM або ідентифікатор таймауту. На відміну від стану оновлення рефа не призводить до повторного рендерингу компонента. Рефи - це "аварійний люк" із парадигми React. Вони корисні, коли вам потрібно працювати з системами, що не належать до React, наприклад, із вбудованими API браузера. Ефекти дозволяють компоненту підключатися до зовнішніх систем та синхронізуватися з ними Це включає роботу з мережею, DOM браузера, анімацією, віджетами, написаними з використанням іншої бібліотеки UI, та іншим не-React кодом. Ефекти – це "аварійний люк" з парадигми React. Не використовуйте ефекти для оркестрування потоку даних у вашому додатку. Якщо ви не взаємодієте із зовнішньою системою, можливо, вам не потрібен ефект. Існують дві рідко використовувані варіанти використанняефекту з відмінностями в часі: Загальний спосіб оптимізації продуктивності повторного рендерингу – пропустити непотрібну роботу. Наприклад, ви можете вказати React повторно використовувати кешовані обчислення або пропустити повторний рендеринг, якщо дані не змінилися з попереднього рендерингу. Щоб пропустити обчислення та непотрібний повторний рендеринг, використовуйте один із цих хуків: Іноді не можна пропустити повторний рендеринг, тому що екран має дійсно оновлюватися. У цьому випадку можна підвищити продуктивність, відокремивши блокуючі оновлення, які повинні бути синхронними (наприклад, введення даних у поле введення), від неблокуючих оновлень, які не повинні блокувати інтерфейс користувача (наприклад, оновлення графіка). Щоб встановити пріоритет рендерингу, використовуйте один із цих хуків: Компонент може отримати доступ до ресурсів, не маючи їх як частину свого стану. Наприклад, компонент може прочитати повідомлення з Promise або прочитати інформацію про стиль із контексту. Щоб прочитати значення з ресурсу, використовуйте цей хук: Ці хуки переважно корисні авторам бібліотек і не часто використовуються в коді програми. Хукі — нововведення у React 16.8, що дозволяє використовувати стан та інші можливості React без написання класів. Перший хук, який ми вивчимо, це функція використаннядержави. Не турбуйтеся, якщо цей приклад буде спочатку незрозумілий. Скоро ми розберемося, як він працює. Ви можете почати вивчати хуки на наступній сторінці. Тут ми розповімо, навіщо ми додали хуки в React, і як вони допоможуть вам писати програми. Примітка React 16.8.0 – це перший реліз, що підтримує хуки.При оновленні версії, не забудьте оновити всі залежності, включаючи React DOM. Підтримка хуків React Native з'явилася у версії 0.59. На конференції React Conf 2018, Софі Алперт (Sophie Alpert) та Ден Абрамов (Dan Abramov) представили хуки, а Райн Флоренс (Ryan Florence) показав, як їх використовувати у додатку. Відео конференції можна переглянути тут: Повна зворотна сумісність Перед тим, як ми продовжимо, зверніть увагу, що хуки: Ми не плануємо видаляти класи з React. Ви можете прочитати більше про стратегію поступового впровадження хуків у розділі нижче. Хуки не змінюють ваші знання про концепції React. Натомість, хуки надають більш прямий доступ до API вже знайомих вам понять: пропсів, стану, контексту, рефів та життєвого циклу. Ми також розглянемо потужний спосіб компонувати ці поняття за допомогою хуків. Щоб розпочати вивчати хуки, перейдіть на наступну сторінку! На цій сторінці ми розповімо про те, навіщо потрібні хуки, та як їх використовувати, не переписуючи наші програми. Хуки вирішують безліч, здавалося б, незв'язаних між собою проблем у React, з якими ми стикалися протягом п'яти років написання та підтримки десятків тисяч компонентів. Якщо ви вивчаєте React, використовуєте його щодня або використовуєте іншу бібліотеку з таким компонентним підходом, ці проблеми напевно здадуться вам знайомими. Важко повторно використати логіку станів між компонентами У React немає способу «приєднати» повторно використовувану поведінку до компоненту (наприклад, підключення до сховища). Якщо ви працювали з React якийсь час, то вам можуть бути знайомі такі патерни, як рендер-пропси та компоненти вищого ладу, які намагаються вирішити цю проблему. Але ці патерни змушують вас змінювати структуру компонентів, що робить код громіздким та важким у підтримці. Якщо ви подивіться на типовий React-додаток у React DevTools, то побачите «пекло обгорток» з компонентів, оточених провайдерами, консьюмерами, компонентами вищого порядку, рендер-пропсами та іншими абстракціями. Хоч ми і можемо відфільтрувати їх у DevTools, все це вказує на глибшу проблему React. Потрібен зручніший спосіб повторно використовувати логіку навколо стану. За допомогою хуків ви можете отримати логіку стану з компонента, щоб її протестувати або повторно використовувати. Хуки дозволяють повторно використовувати логіку стану, не торкаючись дерева компонентів. Завдяки цьому хуки легко використовувати в різних компонентах і ділитися ними з спільнотою. Ми обговоримо це докладніше у розділі Створення власних хуків. Складні компоненти стають важкими для розуміння Нам часто доводилося підтримувати компоненти, які спочатку були простими, але перетворилися на некерований безлад, що складається з логіки стану та побічних ефектів. Кожен метод життєвого циклу часто містить суміш незв'язаної логіки.Наприклад, компоненти можуть завантажувати дані в componentDidMount і componentDidUpdate . метод. Це легко призводить до баг і невідповідностей у додатку. У деяких випадках неможливо розбити компоненти на більш дрібні, тому що логіка стану розкидана всюди. Такі компоненти складно тестувати. різними файлами та ускладнює повторне використання компонентів. Щоб вирішити цю проблему, хуки дозволяють розбити один компонент на маленькі функції за призначенням (наприклад, підписці чи завантаженні даних), а не на основі методів життєвого циклу. Ви також можете контролювати внутрішній стан за допомогою редюсера, щоб поведінка була більш передбачуваною. Класи плутають як людей, так і машини До того ж ускладнення організації коду та його повторного використання, класи створюють суттєвий бар'єр у вивченні React. код стає багатослівним. Люди можуть чудово розуміти пропси, стан та односпрямований потік даних, але все одно плутатися із класами.Відмінності між функціональними і класовими компонентами React і тим, коли їх використовувати, призводять до розбіжностей навіть між досвідченими React-розробниками. До того ж, React існує вже близько п'яти років і ми хочемо переконатися, що він залишиться актуальним протягом наступних п'яти років. Як показують Svelte, Angular, Glimmer та інші технології, компіляція компонентів перед їх виконанням має величезний потенціал у майбутньому. Особливо якщо шаблони не накладають обмежень. Нещодавно ми експериментували зі згортанням компонентів з використанням Prepack і побачили перші перспективні результати. Однак ми помітили, що класові компоненти можуть призводити до ненавмисних патернів, які зводять оптимізацію нанівець. Класи створюють складнощі для інструментів і сьогодні. Наприклад, класи погано мініфікуються, а гаряче перезавантаження (hot reloading) ненадійне і часто ламає їх. Наша мета – надати API, який підвищить ймовірність того, що код можна буде оптимізувати. Щоб вирішити ці проблеми, Хуки дозволяють використовувати більше можливостей React без написання класів. Концептуально, React-компоненти завжди були ближчими до функцій. Хуки забезпечують доступ до функціоналу, але знецінюють досвід використання React. Хуки надають імперативні лазівки і вимагають від вас вивчення складних функціональних чи реактивних підходів. Стратегія поступового впровадження TLDR: Ми не плануємо видаляти класи з React. Ми знаємо, що React-розробники сфокусовані на поставці продукту і не мають часу вивчати новий API кожного релізу. Хуки це щось нове, і, можливо, краще почекати більше прикладів і уроків, перш ніж починати їх вивчення. Ми також розуміємо, що планка для додавання нових примітивів у React є дуже високою.Тому для цікавих читачів ми підготували докладний RFC, в якому можна знайти більше інформації про технічні аспекти вибраного дизайну. Важливо розуміти, що хуки працюють поруч із існуючим кодом, тому ви можете впроваджувати їх поступово. Немає поспіху переходити на хуки. Ми рекомендуємо уникати будь-яких великих переписувань, особливо для існуючих, складних класових компонентів. Вам потрібно буде трохи змінити світогляд, щоб почати «мислити хуками». На наш досвід, найкраще спочатку попрактикуватися використовувати хуки в нових і некритичних компонентах і переконатися, що всі у вашій команді почуваються комфортно з ними. Після того, як ви спробуєте, не соромтеся надіслати нам свій відгук, позитивний чи негативний. Ми маємо намір охопити всі можливі варіанти використання класів у хуках, але ми все ще підтримуватимемо класові компоненти в найближчому майбутньому. У Facebook десятки тисяч компонентів, написаних у вигляді класів, і у нас немає жодних планів їх переписувати. Натомість ми починаємо використовувати хуки в новому коді паралельно з класами. Часті питання Ми підготували для вас сторінку FAQ з відповідями на найчастіші питання про хуки. До кінця цієї сторінки ви повинні мати загальне уявлення про те, які проблеми вирішують хуки, але багато деталей, можливо, залишилися незрозумілими. Не турбуйтесь! Давайте перейдемо на наступну сторінку, де вивчимо хуки на прикладах. Хукі — нововведення у React 16.8, що дозволяє використовувати стан та інші можливості React без написання класів. Хуки – назад сумісні. На цій сторінці ви отримаєте загальне уявлення про хуки. Майте на увазі, що це огляд, який більше підійде досвідченим користувачам React.Наприкінці кожного розділу є такий жовтий блок з детальним поясненням на випадок, якщо ви заплуталися: Докладне пояснення Якщо ви хочете зрозуміти, чому ми додаємо хуки React, прочитайте мотивацію. Розглянемо приклад, у якому рендерується лічильник. Якщо ви натиснете кнопку, значення лічильника буде інкрементовано. У цьому прикладі useState — це хук (Визначення хука дано нижче). Ми викликаємо його, щоб наділити наш функціональний компонент внутрішнім станом. React зберігатиме цей стан між рендерами. Виклик використаннядержав повертає масив з двома елементами, що містить: поточний значення стану та функцію для його оновлення. Цю функцію можна використовувати будь-де, наприклад, в обробнику подій. Вона схожа з this.setState в класах, але не зливає новий і старий стан разом. Порівняння хука useState і this.state наводиться на сторінці Використання хука стану. Єдиний аргумент використаннядержави - це початковий стан. У прикладі вище - це 0, так як наш лічильник починається з нуля. Зауважте, що на відміну від this.state , у разі стан може, але з повинно, бути об'єктом. Вихідне значення аргументу використовується лише за першого рендері. Оголошення кількох змінних стану Хук стану можна використовувати у компоненті більше одного разу. Синтаксис деструктуризації масивів дозволяє нам по-різному називати змінні стани, які ми оголошуємо при виклику використаннядержав. Так як імен цих змінних немає в API useState, React припускає, що якщо ви викликаєте useState багато разів, ви робите це в однаковій послідовності при кожному рендері. Ми розповімо, чому це працює і коли це доцільно, трохи згодом. Хуки – це функції, за допомогою яких ви можете «підчепитися» до стану та методів життєвого циклу React із функціональних компонентів. Хуки не працюють усередині класів — вони дають можливість використовувати React без класів. (Ми не рекомендуємо відразу ж переписувати існуючі компоненти, але за бажання ви можете почати використовувати хуки у своїх нових компонентах.) React містить кілька вбудованих хуків, таких як useState. Ви також можете створювати власні хуки, щоб повторно використовувати їх в інших компонентах. Давайте спочатку розглянемо вбудовані хуки. Вам, швидше за все, доводилося раніше запитувати дані, робити підписки або вручну міняти DOM з React-компонента. Ми розцінюємо ці операції як «побічні ефекти» (або скорочено «ефекти»), оскільки вони можуть впливати на роботу інших компонентів і не можна їх виконати під час рендеру. За допомогою хука ефекту useEffect можна виконувати побічні ефекти з функціонального компонента. Він виконує ту ж роль, що і componentDidMount , componentDidUpdate і componentWillUnmount у React-класах, об'єднавши їх у єдиний API. Ви можете знайти порівняння useEffect і цих методів на сторінці використання ефекту хука. Наприклад, цей компонент встановлює заголовок документа після того, як React оновлює DOM: Коли ви викликаєте useEffect , React отримує вказівку запустити вашу функцію з ефектом після того, як він відправив зміни в DOM. Оскільки ефекти оголошуються всередині компонента, вони мають доступом до його пропсів і стану. За замовчуванням React запускає ефекти після кожного рендеру, включаючи перший рендер. Ми розглянемо докладніше, як це відрізняється від класових методів життєвого циклу на сторінці використання ефекту хука. При необхідності ви можете повернути з ефекту функцію, яка вказує на ефект, як виконати за собою «скидання». Наприклад, цей компонент використовує ефект, щоб передплатити статус друга в мережі, і виконує скидання, відписуючись від нього. У цьому прикладі React буде відписуватися від нашого ChatAPI перед тим, як компонент розмонтується і перед тим, як перезапустити ефект при повторному рендері. Ви можете зробити так, щоб React пропускав повторні підписки, якщо props.friend.id , який ми передали в ChatAPI , залишився без змін. Як і useState , можна використовувати більше ефекту в компоненті: Хуки дають вам можливість організувати побічні ефекти в компоненті пов'язаних частин (наприклад, додавання або скасування підписки), замість того, щоб змушувати вас ділити все відповідно до методів життєвого циклу. Докладне пояснення Ви можете дізнатися більше про useEffect на сторінці Використання ефекту хука. Хуки - це функції JavaScript, які накладають два додаткові правила: Ми розробили спеціальний плагін для лінтера, який допомагає забезпечувати дотримання цих правил. Ми розуміємо, що ці правила можуть здатися трохи незрозумілими та накладати певні обмеження, але вони дуже важливі для правильної роботи хуків. Докладне пояснення Ви можете дізнатись більше на сторінці Правила хуків. 💡 Створення власних хуків Іноді потрібно повторно використовувати однакову логіку стану у кількох компонентах. Традиційно використовувалися два підходи: компоненти вищого ладу та рендер-пропси. За допомогою хуків користувача це завдання вирішується без додавання непотрібних компонентів у ваше дерево. Раніше на цій сторінці ми розглядали компонент FriendStatus, який викликав хуки useState і useEffect, щоб підписатися на статус друга в мережі. Допустимо, ми хочемо ще раз використовувати цю логіку з підпискою, але вже в іншому компоненті. Перш за все, давайте витягнемо цю логіку в хук користувача useFriendStatus Хук приймає friendID як аргумент і повертає змінну, яка показує, чи в мережі наш друг чи ні. Тепер ми можемо використовувати цей хук в обох компонентах: Стани кожного компонента жодним чином не залежать один від одного. Хуки - це спосіб використовувати повторно логіку стану, а чи не сам стан. Більше того, кожне звернення до хука забезпечує цілком ізольований стан. Ви навіть можете використовувати той самий хук кілька разів в одному компоненті. Користувальницькі хуки - це більшою мірою угода, ніж доповнення. Якщо ім'я функції починається з ” use ” і вона викликає інші хуки, ми розцінюємо це як хук користувача. Якщо ви будете дотримуватись угоди прокористування когось при назві хуків, це дозволить нашому плагіну для лінтера знайти баги в коді, який використовує хуки. Є багато підходящих випадків, щоб написати користувальницькі хуки, такі як робота з формами, анімація, декларативні підписки, таймери і, мабуть, багато інших, про які ми навіть не думали. Ми з нетерпінням очікуємо побачити, які ж користувацькі хуки спільнота React зможе придумати. Є ще кілька менш використовуваних вбудованих хуків, які можуть знадобитися. Наприклад, за допомогою useContext ви можете підписатися на контекст React без використання будь-яких вкладень. А хук useReducer дає можливість керувати внутрішнім станом складнішого компонента за допомогою редюсера. Докладне пояснення Ви можете дізнатися більше про всі вбудовані хуки на сторінці API-довідника хуків. Фух, давайте перестанемо поспішати і трохи охолодимо запал! Якщо вам щось незрозуміло або ви хочете дізнатися про щось докладніше, ви можете почати читати наступні сторінки, починаючи з документації хука стану. Ви також можете переглянути API-довідник хуків та FAQ хуків. І нарешті, не проходьте повз вступну сторінку, на якій ви дізнаєтеся чому ми додаємо хуки і як ми плануємо використовувати їх разом із класами без необхідності переписувати наші додатки.Огляд хуків¶
Хуки стану¶
Контекстні хуки¶
Реф хукі¶
Хуки ефектів¶
Хуки продуктивності¶
Хуки ресурсів¶
Інші хуки¶
Введення в хуки
import React,
useState >
from
'react';
function
Example()
// Оголошення змінної стану, яку ми назвемо " count "
const
[count, setCount]
=
useState(0);
return
(
div>
p>Ви клікнули
count>
разp>
button
onClick=()
=>
setCount(count +
1)>>
Натисни на мене
button>
div>
);
>
Короткий огляд хуків
import React,
useState >
from
'react';
function
Example()
// Оголошуємо нову змінну стану " count "
const
[count, setCount]
=
useState(0);
return
(
div>
p>Ви натиснули
count>
разp>
button
onClick=()
=>
setCount(count +
1)>>
Натисни на мене
button>
div>
);
>function
ExampleWithManyStates()
// Оголошуємо кілька змінних станів!
const
[age, setAge]
=
useState(42);
const
[fruit, setFruit]
=
useState('банан');
const
[todos, setTodos]
=
useState([
text:
'Вивчити хуки'
>]);
// .
>import React,
useState, useEffect >
from
'react';
function
Example()
const
[count, setCount]
=
useState(0);
// За принципом componentDidMount та componentDidUpdate:
useEffect(()
=>
// Оновлюємо заголовок документа за допомогою API браузера
document.title =
`Ви натиснули
$count>
раз`;
>);
return
(
div>
p>Ви натиснули
count>
разp>
button
onClick=()
=>
setCount(count +
1)>>
Натисни на мене
button>
div>
);
>import React,
useState, useEffect >
from
'react';
function
FriendStatus(props)
const
[isOnline, setIsOnline]
=
useState(null);
function
handleStatusChange(status)
setIsOnline(status.isOnline);
>
useEffect(()
=>
ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
return
()
=>
ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
>;
>);
if
(isOnline ===
null)
return
'Завантаження. ';
>
return isOnline ?
'У мережі'
:
'Не в мережі';
>function
FriendStatusWithCounter(props)
const
[count, setCount]
=
useState(0);
useEffect(()
=>
document.title =
`Ви натиснули
$count>
раз`;
>);
const
[isOnline, setIsOnline]
=
useState(null);
useEffect(()
=>
ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
return
()
=>
ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
>;
>);
function
handleStatusChange(status)
setIsOnline(status.isOnline);
>
// .
import React,
useState, useEffect >
from
'react';
function
useFriendStatus(friendID)
const
[isOnline, setIsOnline]
=
useState(null);
function
handleStatusChange(status)
setIsOnline(status.isOnline);
>
useEffect(()
=>
ChatAPI.subscribeToFriendStatus(friendID, handleStatusChange);
return
()
=>
ChatAPI.unsubscribeFromFriendStatus(friendID, handleStatusChange);
>;
>);
return isOnline;
>function
FriendStatus(props)
const isOnline =
useFriendStatus(props.friend.id);
if
(isOnline ===
null)
return
'Завантаження. ';
>
return isOnline ?
'У мережі'
:
'Не в мережі';
>function
FriendListItem(props)
const isOnline =
useFriendStatus(props.friend.id);
return
(
li
style=
color: isOnline ?
'green'
:
'black'
>>>
props.friend.name>
li>
);
>function
Example()
const locale =
useContext(LocaleContext);
const theme =
useContext(ThemeContext);
// .
>function
Todos()
const
[todos, dispatch]
=
useReducer(todosReducer);
// .