React уже давно став золотим стандартом у розробці Front End інтерфейсів завдяки своїй гнучкості та потужним можливостям керування станом. Одним із ключових інструментів у його арсеналі є хуки – функції, які дають змогу “підключатися” до життєвого циклу компонентів і керувати станом або побічними ефектами без використання класів. Але що робити, коли стандартні хуки не вирішують конкретного завдання? На допомогу приходять react custom hooks – можливість створювати свої для повторного використання логіки та поліпшення структури застосунку.
А зрозуміти на практиці, що таке фронт енд ви можете на курсах FoxmindEd.
Що таке хуки в React і навіщо потрібні кастомні хуки?
Ще раз, це такі функції, які дають змогу “підключатися” до можливостей React, таких як управління станом або побічні ефекти. Наприклад, найвідоміший з них – useState, який використовується для роботи зі станом у функціональних компонентах.
Кастомні хуки в React дають змогу розробнику винести повторювану логіку в окрему функцію, що робить код чистішим і перевикористовуваним.
Основні принципи роботи з хуками
Для початку розберемося в розумінні базових принципів:
- Хуки викликаються тільки всередині функцій компонентів або інших хуків. Не можна викликати їх усередині циклів, умов або вкладених функцій.
- Порядок виклику хуків критичний. Він має залишатися незмінним під час кожного рендеру компонента.
- Хуки слідують за компонентами. Якщо компонент “помирає”, усі хуки, викликані в ньому, також очищаються.
Коли і чому варто створювати кастомні хуки?
Відповідь проста: коли у вашому проєкті з’являється повторювана логіка. Якщо ви бачите один і той самий код у різних компонентах – це ідеальний момент для створення кастомного інструменту. Наприклад, якщо ви часто працюєте з API-запитами, то замість повторення логіки виклику й обробки даних можна створити хук, який візьме на себе цю роботу.
Створення кастомного хука в React
Тепер давайте подивимося, як створити кастомний хук з нуля. Спойлер: це не так складно, як може здатися на перший погляд.
Як створити простий кастомний хук з нуля?
Досить написати звичайну функцію JavaScript, яка всередині себе використовує один або кілька стандартних хуків React. Наприклад, створимо useWindowWidth, який відстежуватиме ширину вікна:
import { useState, useEffect } from 'react';
function useWindowWidth() {
const [width, setWidth] = useState(window.innerWidth);
useEffect(() => {
const handleResize = () => setWidth(window.innerWidth);
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, []);
return width;
}
Ця функція відстежує зміну розміру вікна і повертає поточну ширину. Тепер її можна застосовувати в будь-якому компоненті, так само як вбудовані хуки.
курси Junior саме для вас.
Приклад реалізації кастомного хука для управління станом
Припустимо, ми хочемо створити хук, який керуватиме станом форми:
function useForm(initialValues) {
const [values, setValues] = useState(initialValues);
const handleChange = (event) => {
setValues({
...values,
[event.target.name]: event.target.value,
});
};
return [values, handleChange];
}
Тепер ви можете використовувати цю функцію в будь-якому компоненті:
const [formValues, handleInputChange] = useForm({ username: '', email: '' });
Як передавати і використовувати дані всередині кастомного хука?
Коли ви створюєте кастомний хук, ви можете передавати йому будь-які дані через параметри, як звичайній функції. У прикладі з useForm ми передаємо початкові значення через аргумент initialValues, а всередині хука керуємо станом за допомогою useState.
Приклади використання кастомних хуків
Тепер давайте розглянемо реальні приклади хуків у react і в складніших сценаріях.
Реалізація кастомних хуків для роботи з API
У роботі з API часто потрібна повторна логіка: надсилання запиту, опрацювання даних, керування помилками і станом завантаження. Усе це можна інкапсулювати в кастомний хук:
function useFetch(url) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
fetch(url)
.then((response) => response.json())
.then((result) => {
setData(result);
setLoading(false);
})
.catch((error) => {
setError(error);
setLoading(false);
});
}, [url]);
return { data, loading, error };
}
Приклад кастомного хука для обробки подій
Припустимо, вам потрібно відстежувати події кліків поза компонентом (наприклад, закриття випадаючого меню). Замість копіювання коду скрізь, де це потрібно, можна створити функцію useOutsideClick:
function useOutsideClick(ref, callback) {
useEffect(() => {
const handleClickOutside = (event) => {
if (ref.current && !ref.current.contains(event.target)) {
callback();
}
};
document.addEventListener('mousedown', handleClickOutside);
return () => {
document.removeEventListener('mousedown', handleClickOutside);
};
}, [ref, callback]);
}
Оптимізація повторного використання логіки через хуки
Кастомні функції дають змогу легко перевикористовувати складну логіку, покращуючи підтримку і масштабованість коду. Наприклад, якщо у вашому застосунку безліч компонентів взаємодіють з API, такі функції допоможуть уникнути дублювання і спростять тестування.
Найкраща практика створення кастомних хуків
Як створити кастомний хук? Адже це – не просто написання функцій, а процес, який вимагає уважного підходу.
Як уникнути типових помилок під час створення хуків?
Важливий момент – правильно керувати залежностями в useEffect. Якщо ви використовуєте зовнішні змінні, додайте їх у масив залежностей, інакше логіка може працювати некоректно.
Рекомендації щодо організації та структури кастомних хуків
Найкраще виділяти їх в окремі файли і групувати за призначенням. Наприклад, функції для роботи з API можна зберігати в папці hooks/api, а для керування станом – у hooks/state.
Поради з тестування та налагодження кастомних хуків
Для тестування зручно використовувати бібліотеки на кшталт react-testing-library. Завжди намагайтеся писати юніт-тести, щоб переконатися, що функції працюють коректно в ізоляції від компонентів.
У вас залишилися запитання про те, як створювати кастомні хуки в React? Запитуйте в коментарях нижче!