Фото Тейлора Мерфі на Unsplash
Ми швидко наближаємося до 2025 року, і React, без сумнівів, залишатиметься одним з найпопулярніших виборів для створення фронтенд-застосунків.
Це не через те, що у нього немає недоліків, а через величезну спільноту та масову популярність, яку React здобув за роки. І не можна забувати про React 19, який обіцяє багато нового, тому React не втратить своєї позиції.
Важко уявити React без хуків, але, на жаль, я часто бачу, як розробники їх надмірно використовують. В результаті їм доводиться вирішувати проблеми з масивами залежностей, непотрібними рендерами та всіма проблемами, які вони створили, оскільки глибоко в їхній свідомості є переконання, що все можна зробити тільки за допомогою хуків в React.
У цій статті я розгляну п'ять принципів, які кожен новий програміст React повинен знати, щоб покращити та спростити свій код.
**1.
Не кожна функція повинна бути хуком (Hook)
Розпочнемо з основ і переглянемо визначення.
Хуки визначаються за допомогою функцій JavaScript. Вони представляють певний тип багаторазової логіки інтерфейсу користувача (UI) і обмежені місцем, де їх можна викликати.
Хуки можуть виглядати як функції, але є кілька відмінностей:
- Хуки можна використовувати тільки у функціональних компонентах або в кастомних хуках (custom hooks).
- Ім’я хука завжди починається з “use”, після якого йде велика буква.
- Якщо кастомний хук не містить викликів інших хуків всередині, це є звичайною функцією, а не хуком. Це важливо, оскільки допомагає визначити, чи є внутрішня логіка стану або ефекти.
Створимо простий кастомний хук під назвою useBoolean, щоб задовольнити ці вимоги.
Ми можемо використовувати його для відкриття/закриття панелей, діалогових вікон, показу/приховування елементів тощо.
Якщо ви подивитесь на офіційну документацію, ви знайдете рекомендацію обгортати будь-які функції, що повертаються з хука, у useCallback, і ми зробимо саме так.
interface ICallbacks {
setFalse: () => void;
setTrue: () => void;
toggle: () => void;
}
const useBoolean = (initialValue: boolean): [boolean, ICallbacks] => {
const [value, setValue] = useState(initialValue);
const setFalse = useCallback(() => {
setValue(false);
}, []);
const setTrue = useCallback(() => {
setValue(true);
}, []);
const toggle = useCallback(() => {
setValue(curValue => !curValue);
}, []);
return [value, {setFalse, setTrue, toggle}];
}
Коли ми згадуємо основи, ми можемо поглибити розуміння та краще зрозуміти деякі нюанси.
2.
Дізнайтесь про повторні рендери
Напевно, ви запитаєте, чому це важливо.
Розуміння того, як працює React і що відбувається, коли ви змінюєте стан компонента через функцію-сеттер, є дуже важливим. На перший погляд може здатися, що ви змінили стан, і результат має з'явитися одразу, але чи так це насправді?
Коли ви розумієте, що відбувається при зміні стану, значно простіше зрозуміти, коли і чому спрацьовують useEffect або інші хуки з масивами залежностей.
Розглянемо простий приклад.
Уявімо, що ми натискаємо кнопку вперше та викликаємо onChangeText, передаючи значення "newValue".
const [text, setText] = useState("defaultValue");
const onChangeText = (value: string) =\> {
// value дорівнює "newValue"
setText(value);
console.log(text); // Яке значення буде тут?
}
Може здатися, що в консолі ми повинні побачити "newValue", але насправді там буде "defaultValue". Чому? Тому що нове значення стане доступним тільки після повторного рендеру.
Ось кроки, що відбуваються:
- Ми змінюємо стан через функцію-сеттер, даючи React вказівку виконати дію.
- Рендер. React викликає ваш компонент, щоб обчислити новий JSX, який буде повернений.
- Підтвердження. Після обчислення змін React змінить DOM, застосовуючи мінімальні дії.
4.
Після попередніх кроків ви побачите візуальні зміни на екрані ("рендеринг браузера").
Щоразу, коли ви хочете змінити значення в стані, треба пам'ятати, що ці кроки виконуються кожного разу.
3. useState не завжди правильне рішення
У React є два способи керувати станом компонента — useState та useReducer. Другий варіант менш популярний, оскільки призначений для складніших об'єктів у стані, і чесно кажучи, на перший погляд здається занадто складним для нових програмістів, але це не так.
Однак useState виглядає дуже простим і зрозумілим, тому нові програмісти часто використовують його більше, ніж потрібно.
В залежності від взаємодій користувача, він призначений для керування станом з метою перерендеру компонентів. Якщо ви хочете зберегти щось без рендерингу, ймовірно, не слід класти це в стан.
useRef буде найкращим варіантом.
Вам не потрібен useState, якщо:
- Ви хочете зберігати деякі значення під час перерендерів, не показуючи їх користувачу.
- У вас уже є дані в стані, або ви отримуєте їх через props, але потрібно їх перетворити; вам не потрібно зберігати це нове значення в новому об'єкті useState, створіть нову змінну і працюйте з нею без виклику зайвих перерендерів.
Вам потрібно зберігати значення в стані, якщо:
- Ви хочете перерисовувати компонент при зміні значення; найбільш популярні приклади — показ/сховання панелей, спінерів, повідомлень про помилки та модифікація масивів.
Спрощуйте свій код із цього:
/**
Цей підхід призводить до зайвих перерендерів і непотрібного
використання useEffect.
Коли змінюються ім’я або опис,
і React перерендерує компонент,
React перевірить, чи є функціональність, що залежить від цих значень.
useEffect буде викликано, коли ім’я або опис зміняться,
що створить новий перерендер.
/**
const [name, setName] = useState('name');
const { description, index } = props;
const [fullName, setFullName] = useState('');
useEffect(() => {
setFullName(`${name} - ${description}`);
}, [name, description]);
На це:
/**
Ми можемо використовувати стандартну поведінку React і отримувати правильне значення, коли ім’я
або опис змінюються, без виклику ще одного перерендеру.
**/
const [name, setName] = useState();
const { description, index } = props;
const nameWithDescription = `${name} - ${description}`;
4. З обережністю використовуйте useEffect
Ми використовували специфічні методи життєвого циклу з класовими компонентами в окремих випадках.
Оскільки з версії React 16.8 може здатися, що ми маємо один хук useEffect для всього.
Не для всього, але через відсутність документації та неймовірний ажіотаж навколо хуків у 2019 році, з’явилася тенденція використовувати його в усіх можливих місцях.
Давайте подивимося на офіційну документацію:
useEffect
— це хук React, який дозволяє синхронізувати компонент з зовнішньою системою.
Але насправді ми використовуємо useEffect значно більше, ніж це необхідно. Він відмінно підходить для отримання даних, коли компонент монтується, але, на жаль, нові програмісти часто використовують цей хук для зміни стану, що не є найкращим рішенням.
Зупиніться і перегляньте свій код, якщо ви виявили, що пишете один useEffect за іншим всередині одного компонента.
Зазвичай вам вони не потрібні, і ви можете швидко вилучити їх.
Вам не потрібен useEffect, якщо:
- Вам потрібно обробляти події користувача (кліки); якщо ви знаєте, які дії викликають певну логіку, не використовуйте useEffect для виклику цієї логіки.
- Вам потрібно трансформувати дані для рендерингу, наприклад, конкатенувати рядки зі стану або пропсів.
Поміщення реактивних значень чилогіки у масив залежностей може викликати надмірні виклики useEffect, що призведе до безкінечних циклів.
[
Підводні камені useEffect для програмістів React
Спочатку це здається простим, але цей хук може принести багато болю, якщо ви не знаєте деяких нюансів
betterprogramming.pub
](https://betterprogramming.pub/pitfalls-of-useeffect-for-react-programmers-4ac3f73284b5?source=post_page-----4967cd9d4eb4--------------------------------)
Вам варто вибрати useEffect, якщо:
- ви хочете отримати дані під час монтування компонента, встановлювати інтервали та використовувати його для синхронізації стану з іншими системами
5. Не бійтеся useRef
На жаль, useRef недооцінений. Це не один з найпопулярніших хуків, але він дуже корисний.
Знаючи, як і де використовувати useRef, можна досягти великих результатів.
Розпочнемо з основ.
useRef — це хук React, який дозволяє посилатися на значення, яке не потрібне для рендерингу. —з офіційної документації React.
React запам'ятає значення, яке ви створюєте через useRef, будь то Javascript-об'єкт, який посилається на елемент у DOM, або просте значення, і воно не буде втрачено під час повторних рендерів.
Що це дає нам?
- Ми можемо легко отримати доступ до елементів у DOM. Наприклад, ви можете отримати значення поля введення, сфокусуватися на конкретних елементах, отримати їх висоту та ширину, прокручувати до певної частини екрана і багато іншого.
- Ви можете зберігати будь-які дані, які вам потрібні, без повторного рендерингу компонентів.
Наприклад, якщо вам потрібен лічильник або таймер, вибирайте useRef, а не useState.
Приклади:
// посилання на число
const refCount = useRef(0);
// посилання на елемент введення
const refInputField = useRef(null);
/**
Щоб отримати доступ до значення, потрібно використовувати властивість current.
useRef не викликає повторні рендери, тому ви можете використовувати його всередині useEffect,
не хвилюючись про масив залежностей.
*/
const onClick = () => {
refCount.current = refCount.current + 1;
refInputField.current.focus();
}
return (
<>
<button onClick={onClick}>Click me!</button>
</>
);
Хуки — це чудово, і вам варто їх використовувати. Ви можете досягти багато чого, якщо зрозумієте, як працює React, і правильно застосовуватимете хуки.
Це все, що я хотів розповісти для нових розробників React. Сподіваюся, ці поради будуть корисними.
Перекладено з: Learning React: 5 Important Principles About Hooks You Have To Know