Пошук уроків, статей та іншого контенту
Розберетеся, що таке Hooks, навіщо вони потрібні та як змінили підхід до створення функціональних компонентів.
Hooks — це спеціальні функції React, які дають змогу використовувати можливості React у функціональних компонентах.
За допомогою Hooks функціональний компонент може:
зберігати стан;
реагувати на зміни стану та властивостей;
виконувати побічні ефекти;
використовувати інші можливості React;
повторно використовувати логіку в різних компонентах.
Назви вбудованих Hooks починаються з use, наприклад:
useState;
useEffect;
useContext;
useRef.
До появи Hooks стан і складну логіку зазвичай використовували в класових компонентах.
import React from 'react';
class Counter extends React.Component {
state = {
count: 0,
};
increase = () => {
this.setState({
count: this.state.count + 1,
});
};
render() {
return (
<button onClick={this.increase}>
Натиснуто: {this.state.count}
</button>
);
}
}Класові компоненти працюють, але мають додатковий синтаксис:
class;
this;
метод render;
this.state;
this.setState;
прив’язування методів до компонента.
Hooks дозволили зберігати стан і використовувати логіку у звичайних функціях:
import { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
return (
<button onClick={() => setCount(count + 1)}>
Натиснуто: {count}
</button>
);
}
export default Counter;Такий код коротший і зазвичай простіше читається.
Звичайний функціональний компонент може просто повертати JSX:
function Greeting({ name }) {
return <h1>Привіт, {name}!</h1>;
}Такий компонент не має власного стану. Його результат залежить від отриманих props.
За допомогою Hook useState компонент може зберігати власні дані:
import { useState } from 'react';
function Greeting() {
const [name, setName] = useState('');
return (
<div>
<input
value={name}
onChange={(event) => setName(event.target.value)}
placeholder="Введіть ім’я"
/>
<h1>Привіт, {name || 'незнайомцю'}!</h1>
</div>
);
}
export default Greeting;Тепер компонент:
зберігає значення поля в стані name;
оновлює стан після введення кожного символу;
повторно відображається після зміни стану.
useStateuseState — один із найпоширеніших Hooks. Він додає компоненту стан.
const [state, setState] = useState(initialValue);useState повертає масив із двох елементів:
поточне значення стану;
функцію для його оновлення.
Наприклад:
const [count, setCount] = useState(0);Тут:
count — поточне значення;
setCount — функція оновлення;
0 — початкове значення.
Коли викликається функція оновлення, React змінює стан і повторно відображає компонент:
setCount(count + 1);import { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
function increase() {
setCount(count + 1);
}
function decrease() {
setCount(count - 1);
}
function reset() {
setCount(0);
}
return (
<section>
<h1>Лічильник</h1>
<p>Поточне значення: {count}</p>
<button onClick={decrease}>−1</button>
<button onClick={reset}>Скинути</button>
<button onClick={increase}>+1</button>
</section>
);
}
export default Counter;У цьому прикладі count не є звичайною локальною змінною. Якщо змінити звичайну змінну, React не дізнається про це і не оновить інтерфейс. Функція setCount повідомляє React, що стан змінився.
Якщо нове значення залежить від попереднього, краще передавати в setter функцію:
setCount((previousCount) => previousCount + 1);Це особливо корисно, коли потрібно виконати кілька оновлень поспіль:
import { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
function increaseTwice() {
setCount((previousCount) => previousCount + 1);
setCount((previousCount) => previousCount + 1);
}
return (
<div>
<p>Значення: {count}</p>
<button onClick={increaseTwice}>Збільшити на 2</button>
</div>
);
}
export default Counter;Функція отримує актуальне попереднє значення та повертає нове.
useState відповідає за стан, але React має й інші Hooks.
useEffectuseEffect використовують для побічних ефектів — дій, які потрібно виконати після відображення компонента або після зміни певних значень.
Приклад із заголовком вкладки:
import { useEffect, useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
useEffect(() => {
document.title = `Лічильник: ${count}`;
}, [count]);
return (
<button onClick={() => setCount((previousCount) => previousCount + 1)}>
Натиснуто: {count}
</button>
);
}
export default Counter;Масив [count] означає, що ефект потрібно повторно виконувати після зміни count.
У цьому уроці важливо запам’ятати головне: useEffect — також Hook, а всі Hooks дають функціональному компоненту доступ до певної можливості React.
Hooks можна об’єднувати у власні функції. Такі функції називають власними Hooks. Їхні назви також повинні починатися з use.
Наприклад:
import { useState } from 'react';
function useToggle(initialValue = false) {
const [value, setValue] = useState(initialValue);
function toggle() {
setValue((previousValue) => !previousValue);
}
return [value, toggle];
}
function Menu() {
const [isOpen, toggleMenu] = useToggle();
return (
<div>
<button onClick={toggleMenu}>
{isOpen ? 'Закрити меню' : 'Відкрити меню'}
</button>
{isOpen && <p>Меню відкрите</p>}
</div>
);
}
export default Menu;useToggle приховує логіку перемикання значення. Інші компоненти можуть повторно використовувати цю логіку без копіювання коду.
Hooks потрібно використовувати за певними правилами.
Не викликайте Hook всередині:
if;
for;
while;
вкладених функцій;
обробників подій.
Правильно:
function Component() {
const [isVisible, setIsVisible] = useState(true);
if (!isVisible) {
return null;
}
return <p>Компонент видимий</p>;
}Неправильно:
function Component({ shouldUseState }) {
if (shouldUseState) {
const [value, setValue] = useState('');
}
return <p>Компонент</p>;
}React має викликати Hooks у тому самому порядку під час кожного відображення компонента. Умовний виклик може порушити цей порядок.
Правильно:
function Profile() {
const [name, setName] = useState('Олена');
return <p>{name}</p>;
}Також Hook можна викликати всередині власного Hook:
function useName() {
const [name, setName] = useState('');
return [name, setName];
}Не слід викликати Hook у звичайній функції, яка не є компонентом і не є власним Hook.
Hooks зробили функціональні компоненти основним способом написання компонентів у сучасному React.
Завдяки Hooks:
стан можна використовувати без класів;
логіку легше читати та тестувати;
однакову логіку можна винести у власний Hook;
компонентам не потрібен метод render;
код стає компактнішим;
різні частини логіки простіше розділяти.
Функціональний компонент тепер може бути не лише простим шаблоном JSX, а повноцінним компонентом зі станом і поведінкою.
Неправильно:
count = count + 1;Стан потрібно змінювати через setter:
setCount((previousCount) => previousCount + 1);Власний Hook має починатися з use.
Правильно:
function useToggle() {
// логіка Hook
}Назва toggleState не повідомляє React та іншим розробникам, що ця функція є власним Hook.
Неправильно:
if (isLoggedIn) {
const [name, setName] = useState('');
}Hook потрібно викликати на верхньому рівні компонента, а умову застосувати до результату або до JSX.
Hooks — це спеціальні функції React для використання його можливостей у функціональних компонентах.
useState додає компоненту стан.
Оновлення стану виконують через setter, наприклад setCount.
Hooks потрібно викликати лише на верхньому рівні функціонального компонента або власного Hook.
Назви власних Hooks починаються з use.
Hooks зробили функціональні компоненти зручним способом створення компонентів зі станом і поведінкою.