Використання хука стану
These docs are old and won’t be updated. Go to react.dev for the new React docs.
These new documentation pages teach modern React and include live examples:
Хуки — це новинка в React 16.8. Вони дозволяють вам використовувати стан та інші можливості React без написання класу.
На початковій сторінці ми ознайомились з хуками на цьому прикладі:
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>
);
}
Ми розпочнемо вивчення хуків, порівнюючи цей код з еквівалентним кодом на основі класу.
Еквівалентний приклад з класом
Якщо ви вже використовували класи в React, цей код має бути знайомим:
class Example extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 0
};
}
render() {
return (
<div>
<p>Ви натиснули {this.state.count} разів</p>
<button onClick={() => this.setState({ count: this.state.count + 1 })}>
Натисни мене
</button>
</div>
);
}
}
Стан ініціалізується як { count: 0 }
і ми інкрементуємо state.count
, коли користувач натискає на кнопку, викликаючи this.setState()
. Ми будемо використовувати фрагменти коду цього класу на цій сторінці.
Примітка
Ви можете поцікавитись, чому ми використовуємо звичайний лічильник замість більш реального прикладу. Це зроблено для того, щоб ви могли сконцентруватись на API під час ваших перших кроків з хуками.
Хуки та функціональні компоненти
Нагадаємо, що функціональні компоненти в React виглядають так:
const Example = (props) => {
// Тут можна використовувати хуки!
return <div />;
}
або так:
function Example(props) {
// Тут можна використовувати хуки!
return <div />;
}
Раніше ви могли знати, що такі компоненти відомі як “компоненти без стану”. Зараз ми покажемо, як додавати до них стан, а тому надалі ми будемо називати їх “функціональні компоненти”.
Хуки не працюють всередині класів. Але ви можете використовувати їх замість написання класів.
Що таке хук?
Наш наступний приклад починається імпортом хука useState
із React:
import React, { useState } from 'react';
function Example() {
// ...
}
Що таке хук? Хук — це спеціальна функція, що дозволяє вам “зачепитись” за можливості React. Наприклад, хук useState
дозволяє вам додавати стан до функціональних компонентів. Ми вивчимо інші хуки дещо пізніше.
Коли я маю використовувати хук? Якщо ви пишете функціональний компонент і розумієте, що вам потрібно додати деякий стан до нього, раніше ви мали перетворювати його у клас. Зараз ви можете використати хук усередині функціонального компонента. Саме це ми зробимо зараз!
Примітка:
Є кілька особливих правил про те, коли ви можете застосовувати хуки всередині компонента, а коли ні. Ми дізнаємось про них у розділі Правила хуків.
Оголошення змінної стану
У класі ми ініціалізували стан count
зі значенням 0
, встановивши this.state
рівним { count: 0 }
у конструкторі:
class Example extends React.Component {
constructor(props) {
super(props);
this.state = { count: 0 }; }
У функціональному компоненті ми не маємо this
, а тому не можемо присвоювати чи зчитувати this.state
. Натомість, ми викличемо хук useState
у нашому компоненті напряму:
import React, { useState } from 'react';
function Example() {
// Оголошуємо нову змінну стану, яку назвемо "count" const [count, setCount] = useState(0);
Що робить виклик useState
? Він оголошує “змінну стану”. Наша змінна зветься count
, але ми могли назвати її як завгодно, наприклад banana
. Таким чином, ми “зберігаємо” деякі значення між викликами функції. useState
— це новий спосіб використання тих можливостей, що їх this.state
надає у класі. Зазвичай, змінні “зникають” після виходу з функції, але React збереже змінні стану.
Які аргументи ми передаємо в useState
? Єдиним аргументом хука useState()
є початковий стан. На відміну від класів, стан не повинен бути об’єктом. Ми можемо зберігати число чи рядок, якщо це все, що нам потрібно. У нашому прикладі ми рахуємо кількість кліків користувача, а отже, передаємо 0
як початковий стан нашої змінної. (Якщо нам потрібно зберегти два різних значення у стані, ми маємо викликати useState()
двічі.)
Що повертає useState
? Він повертає пару значень: поточний стан і функцію, яка його оновлює. Ось чому ми написали const [count, setCount] = useState()
. Це нагадує this.state.count
та this.setState
у класі, але ви отримуєте їх у парі. Якщо ви не знайомі з синтаксисом, який ми використали, ми повернемось до нього в кінці цієї сторінки.
Тепер ми знаємо, що робить хук useState
, а тому наш приклад повинен бути більш зрозумілим:
import React, { useState } from 'react';
function Example() {
// Оголошуємо нову змінну стану, яку назвемо "count" const [count, setCount] = useState(0);
Ми оголошуємо змінну count
і встановлюємо їй значення 0
. React запам’ятає її поточне значення між повторними рендерами і надасть актуальне значення у нашу функцію. Якщо нам потрібно оновити поточний count
, ми можемо викликати setCount
.
Примітка
Можливо ви запитаєте: чому
useState
назвали, а неcreateState
?“Create” (створити) є не зовсім точним, оскільки стан створюється тільки під час першого рендеру нашого компонента. Під час наступних рендерів
useState
повертає поточний стан. Інакше це був би не “стан” взагалі! Також є причина тому, що імена хуків завжди починаються зuse
. Про неї ми дізнаємось у розділі Правила хуків.
Зчитування стану
Коли ми хочемо відобразити поточне значення лічильника у класі, ми зчитуємо значення this.state.count
:
<p>Ви натиснули {this.state.count} разів</p>
У функції ми можемо напряму використовувати count
:
<p>Ви натиснули {count} разів</p>
Оновлення стану
У класі ми маємо викликати this.setState()
для оновлення стану count
:
<button onClick={() => this.setState({ count: this.state.count + 1 })}> Натисни мене
</button>
У функції ми вже маємо setCount
і count
у ролі змінних, а тому this
нам не потрібен:
<button onClick={() => setCount(count + 1)}> Натисни мене
</button>
Підсумок
Давайте крок за кроком повторимо те, що ми вивчили і перевіримо наші знання.
1: import React, { useState } from 'react'; 2:
3: function Example() {
4: const [count, setCount] = useState(0); 5:
6: return (
7: <div>
8: <p>Ви натиснули {count} разів</p>
9: <button onClick={() => setCount(count + 1)}>10: Натисни мене
11: </button>
12: </div>
13: );
14: }
- Рядок 1: Ми імпортуємо хук
useState
із React. Це дозволить нам зберігати локальний стан у функціональному компоненті. - Рядок 4: Усередині компоненту
Example
, викликавши хукuseState
, ми оголошуємо нову змінну стану. Хук повертає пару значень, яким ми даємо ім’я. Ми називаємо нашу зміннуcount
, тому що вона зберігає кількість кліків на кнопку. Ми ініціалізуємо її нулем, передавши0
, як єдиний аргументuseState
. Друге значення, повернуте хуком, є функцією. Оскільки вона дозволяє нам оновлюватиcount
, ми назвемо їїsetCount
. - Рядок 9: Коли користувач натискає кнопку, ми викликаємо
setCount
із новим значенням. React повторно відрендерить компонентExample
, передавши йому оновлене значенняcount
.
Спочатку все це може здатись надто складним. Не поспішайте! Якщо ви заплутались з поясненням, перегляньте код ще раз і спробуйте прочитати його з початку до кінця. Ми обіцяємо, що коли ви спробуєте “забути”, як стан працює в класах, і поглянете на цей код свіжим поглядом, то все відразу стане на свої місця.
Порада: Що означають квадратні дужки?
Ви могли звернути увагу на квадратні дужки під час оголошення змінної стану:
const [count, setCount] = useState(0);
Імена зліва не є частиною React API. Ви вільні обирати імена ваших власних змінних стану:
const [fruit, setFruit] = useState('банан');
Такий синтаксис JavaScript називається “деструктуризація масивів”. Це означає, що ми створюємо дві нові змінні — fruit
та setFruit
, де fruit
зберігає перше значення, повернуте useState
, а setFruit
— друге. Таке присвоєння рівнозначне коду:
var fruitStateVariable = useState('банан'); // Повертає пару
var fruit = fruitStateVariable[0]; // Перший елемент пари
var setFruit = fruitStateVariable[1]; // Другий елемент пари
Після оголошення змінної стану за допомогою виклику useState
, ми отримуємо пару — масив із двох елементів. Перший елемент є поточним значенням, а другий — функцією, що дозволяє оновити його. Використання [0]
і [1]
для доступу до них може заплутати, тому що індекси не мають особливого значення. Саме тому ми використовуємо деструктуризацію масиву.
Примітка
Ви можете поцікавитись, звідки React знає про те, якому компоненту відповідає
useState
, оскільки ми не передаємо йому нічого подібного доthis
. Ми дамо відповідь на це та багато інших питань у розділі FAQ.
Порада: Використання кількох змінних стану
Оголошення змінних стану у вигляді пари [something, setSomething]
також є корисним у тому сенсі, що воно дає нам можливість давати різні імена різним змінним стану, якщо нам потрібно використати їх декілька:
function ExampleWithManyStates() {
// Оголошуємо кілька змінних стану!
const [age, setAge] = useState(42);
const [fruit, setFruit] = useState('banana');
const [todos, setTodos] = useState([{ text: 'Learn Hooks' }]);
У компоненті вище ми маємо age
, fruit
і todos
у якості локальних змінних і можемо оновлювати кожну з них окремо:
function handleOrangeClick() {
// Схоже на this.setState({ fruit: 'апельсин' })
setFruit('апельсин');
}
Ви не зобов’язані використовувати багато змінних стану. Змінні стану можуть так само зберігати об’єкти і масиви, а отже, ви й досі можете групувати пов’язані дані. Зверніть увагу, що на відміну від this.setState
у класі, оновлення змінної стану завжди заміняє її замість злиття.
Ви можете знайти більше рекомендацій про розділення незалежних змінних стану у FAQ.
Наступні кроки
На цій сторінці ми дізнались про один з хуків, які нам надає React, із назвою useState
. Іноді ми будемо посилатись на нього як на “хук стану”. Він дозволяє нам додавати локальний стан до функціональних компонентів, що ми і зробили вперше!
Також ми дізнались більше про хуки в цілому. Хуки — це функції, що дозволять вам “зачепитись” за можливості React у функціональних компонентах. Їхні імена завжди починаються з use
. Також існує ще кілька хуків, про які ми поки що не знаємо.
Настав час перейти до вивчення наступного хука, а саме — useEffect
. Він дозволяє виконувати побічні ефекти в компонентах і нагадує методи життєвого циклу в класах.