Детальний посібник з рефів у React, що фокусується на useRef та createRef. Дізнайтеся, як і коли використовувати кожен з них для ефективного управління компонентами та доступу до DOM у глобальних застосунках.
Рефи в React: Демістифікація useRef та createRef
У динамічному світі розробки на React ефективне управління станом компонентів та взаємодія з об'єктною моделлю документа (DOM) є надзвичайно важливим. Рефи (Refs) в React надають механізм для доступу та прямої маніпуляції DOM-елементами або компонентами React. Два основні методи створення рефів — це useRef
та createRef
. Хоча обидва служать для створення рефів, вони відрізняються своєю реалізацією та сценаріями використання. Цей посібник має на меті демістифікувати ці два підходи, надаючи ясність щодо того, коли і як ефективно використовувати кожен з них у ваших проєктах на React, особливо при розробці для глобальної аудиторії.
Розуміння рефів у React
Реф (скорочення від reference, посилання) — це функція React, яка дозволяє отримати прямий доступ до вузла DOM або компонента React. Це особливо корисно, коли вам потрібно:
- Безпосередньо маніпулювати DOM-елементом, наприклад, фокусувати поле вводу.
- Отримувати доступ до методів або властивостей дочірнього компонента.
- Керувати значеннями, які зберігаються між рендерами, не викликаючи повторних рендерів (подібно до змінних екземпляра в класових компонентах).
Хоча React заохочує декларативний підхід, де інтерфейс користувача керується через стан та пропси, існують ситуації, коли необхідна пряма маніпуляція. Рефи надають спосіб подолати розрив між декларативною природою React та імперативними операціями з DOM.
createRef
: підхід для класових компонентів
createRef
— це метод, що надається React. Він переважно використовується в класових компонентах для створення рефів. Кожного разу, коли створюється екземпляр класового компонента, createRef
створює новий об'єкт рефа. Це гарантує, що кожен екземпляр компонента має свій унікальний реф.
Синтаксис та використання
Щоб використовувати createRef
, ви спочатку оголошуєте реф у вашому класовому компоненті, зазвичай у конструкторі. Потім ви прикріплюєте реф до DOM-елемента або компонента за допомогою атрибута ref
.
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.myRef = React.createRef();
}
componentDidMount() {
// Отримуємо доступ до DOM-елемента після монтування компонента
this.myRef.current.focus();
}
render() {
return ;
}
}
У цьому прикладі this.myRef
створюється за допомогою React.createRef()
. Потім він присвоюється атрибуту ref
елемента input. Після монтування компонента (в componentDidMount
) ви можете отримати доступ до фактичного вузла DOM за допомогою this.myRef.current
і виконувати над ним операції (у цьому випадку — фокусування поля вводу).
Приклад: Фокусування поля вводу
Розглянемо сценарій, коли ви хочете автоматично фокусувати поле вводу при монтуванні компонента. Це поширений випадок використання рефів, особливо у формах або інтерактивних елементах.
class FocusInput extends React.Component {
constructor(props) {
super(props);
this.inputRef = React.createRef();
}
componentDidMount() {
this.inputRef.current.focus();
}
render() {
return (
);
}
}
У цьому прикладі FocusInput
фокусує поле вводу одразу після монтування. Це може покращити користувацький досвід, спрямовуючи увагу користувача на елемент вводу, щойно компонент буде відрендерений.
Важливі аспекти використання createRef
- Лише для класових компонентів:
createRef
призначений для використання в класових компонентах. Хоча технічно він може працювати і у функціональних компонентах, це не є його цільовим призначенням і може призвести до непередбачуваної поведінки. - Новий реф для кожного екземпляра: Кожен екземпляр класового компонента отримує свій власний
createRef
. Це важливо для підтримки ізоляції між екземплярами компонентів.
useRef
: хук для функціональних компонентів
useRef
— це хук, який був представлений у React 16.8. Він надає спосіб створювати мутабельні об'єкти рефів у функціональних компонентах. На відміну від createRef
, useRef
повертає той самий об'єкт рефа при кожному рендері компонента. Це робить його ідеальним для збереження значень між рендерами без ініціювання повторних рендерів.
Синтаксис та використання
Використання useRef
є простим. Ви викликаєте хук useRef
, передаючи початкове значення. Хук повертає об'єкт з властивістю .current
, яку ви можете використовувати для доступу та зміни значення.
import React, { useRef, useEffect } from 'react';
function MyFunctionalComponent() {
const myRef = useRef(null);
useEffect(() => {
// Отримуємо доступ до DOM-елемента після монтування компонента
if (myRef.current) {
myRef.current.focus();
}
}, []);
return ;
}
У цьому прикладі useRef(null)
створює реф з початковим значенням null
. Хук useEffect
використовується для доступу до DOM-елемента після монтування компонента. Властивість myRef.current
містить посилання на елемент input, що дозволяє вам його сфокусувати.
Приклад: Відстеження попередніх значень пропсів
Одним із потужних сценаріїв використання useRef
є відстеження попереднього значення пропа. Оскільки зміни в рефах не викликають повторних рендерів, ви можете використовувати їх для зберігання значень, які ви хочете зберегти між рендерами, не впливаючи на інтерфейс користувача.
import React, { useRef, useEffect } from 'react';
function PreviousValueComponent({ value }) {
const previousValue = useRef();
useEffect(() => {
previousValue.current = value;
}, [value]);
return (
Поточне значення: {value}
Попереднє значення: {previousValue.current}
);
}
У цьому прикладі previousValue.current
зберігає попереднє значення пропа value
. Хук useEffect
оновлює реф щоразу, коли змінюється проп value
. Це дозволяє порівнювати поточне та попереднє значення, що може бути корисним для виявлення змін або реалізації анімацій.
Важливі аспекти використання useRef
- Лише для функціональних компонентів:
useRef
є хуком і може використовуватися тільки в межах функціональних компонентів або кастомних хуків. - Зберігається між рендерами: Хук
useRef
повертає той самий об'єкт рефа при кожному рендері. Це є ключовим для його здатності зберігати значення без ініціювання повторних рендерів. - Мутабельна властивість
.current
: Ви можете безпосередньо змінювати властивість.current
об'єкта рефа. - Початкове значення: Ви можете надати початкове значення для
useRef
. Це значення буде присвоєно властивості.current
при першому рендері компонента. - Без повторних рендерів: Зміна властивості
.current
рефа не викликає повторного рендеру компонента.
useRef
проти createRef
: Детальне порівняння
Тепер, коли ми розглянули useRef
та createRef
окремо, порівняймо їх, щоб виділити ключові відмінності та визначити, коли вибирати один над іншим.
Характеристика | useRef |
createRef |
---|---|---|
Тип компонента | Функціональні компоненти | Класові компоненти |
Хук чи метод | Хук | Метод |
Екземпляр рефа | Повертає той самий об'єкт рефа при кожному рендері | Створює новий об'єкт рефа для кожного екземпляра компонента |
Випадки використання |
|
|
Вибір правильного рефа: Посібник для прийняття рішень
Ось простий посібник, який допоможе вам вибрати між useRef
та createRef
:
- Ви працюєте з функціональним компонентом? Використовуйте
useRef
. - Ви працюєте з класовим компонентом? Використовуйте
createRef
. - Вам потрібно зберегти значення між рендерами без ініціювання повторних рендерів? Використовуйте
useRef
. - Вам потрібно відстежувати попереднє значення пропа? Використовуйте
useRef
.
Поза маніпуляціями з DOM: Розширені сценарії використання рефів
Хоча доступ до DOM-елементів та їхня маніпуляція є основним випадком використання рефів, вони пропонують можливості, що виходять за рамки цієї основної функціональності. Розглянемо деякі розширені сценарії, де рефи можуть бути особливо корисними.
1. Доступ до методів дочірніх компонентів
Рефи можна використовувати для доступу до методів, визначених у дочірніх компонентах. Це дозволяє батьківському компоненту викликати дії або отримувати дані від своїх дочірніх елементів напряму. Цей підхід особливо корисний, коли вам потрібен детальний контроль над дочірніми компонентами.
class ParentComponent extends React.Component {
constructor(props) {
super(props);
this.childRef = React.createRef();
}
handleClick = () => {
// Викликаємо метод дочірнього компонента
this.childRef.current.doSomething();
};
render() {
return (
);
}
}
class ChildComponent extends React.Component {
doSomething = () => {
console.log('Дію дочірнього компонента викликано!');
};
render() {
return Це дочірній компонент.;
}
}
У цьому прикладі ParentComponent
використовує реф для доступу до ChildComponent
та виклику його методу doSomething
.
2. Керування фокусом та виділенням
Рефи є неоціненними для керування фокусом та виділенням у полях вводу та інших інтерактивних елементах. Це має вирішальне значення для створення доступних та зручних для користувача інтерфейсів.
import React, { useRef, useEffect } from 'react';
function FocusOnMount() {
const inputRef = useRef(null);
useEffect(() => {
if (inputRef.current) {
inputRef.current.focus();
inputRef.current.select(); // Виділяємо текст у полі вводу
}
}, []);
return ;
}
Цей приклад фокусує поле вводу та виділяє його текст, щойно компонент монтується.
3. Анімація елементів
Рефи можна використовувати разом з бібліотеками анімації (такими як GreenSock або Framer Motion) для прямої маніпуляції DOM та створення складних анімацій. Це дозволяє здійснювати детальний контроль над послідовностями анімації.
Приклад з використанням ванільного JavaScript для простоти:
import React, { useRef, useEffect } from 'react';
function AnimatedBox() {
const boxRef = useRef(null);
useEffect(() => {
const box = boxRef.current;
if (box) {
// Проста анімація: переміщуємо блок праворуч
box.animate(
[
{ transform: 'translateX(0)' },
{ transform: 'translateX(100px)' },
],
{
duration: 1000, // 1 секунда
iterations: Infinity, // Повторювати нескінченно
direction: 'alternate', // у зворотному напрямку
}
);
}
}, []);
return ;
}
Цей приклад використовує Web Animations API для анімації простого блоку, переміщуючи його вперед і назад по горизонталі.
Найкращі практики використання рефів React у глобальних застосунках
При розробці застосунків на React для глобальної аудиторії важливо враховувати, як рефи взаємодіють з інтернаціоналізацією (i18n) та локалізацією (l10n). Ось деякі найкращі практики:
1. Доступність (A11y)
Переконайтеся, що ваше використання рефів не впливає негативно на доступність. Наприклад, при програмному фокусуванні елементів враховуйте порядок фокусування користувача та чи є зміна фокусу доречною для скрінрідерів та користувачів, що використовують клавіатуру.
import React, { useRef, useEffect } from 'react';
function AccessibleFocus() {
const buttonRef = useRef(null);
useEffect(() => {
const button = buttonRef.current;
if (button) {
// Фокусуємо, тільки якщо кнопка ще не сфокусована користувачем
if (document.activeElement !== button) {
button.focus();
}
}
}, []);
return ;
}
2. Інтернаціоналізовані поля вводу
Працюючи з полями вводу, пам'ятайте про різні методи вводу та набори символів, що використовуються в різних мовах. Переконайтеся, що ваші маніпуляції на основі рефів (наприклад, виділення, позиція курсора) коректно працюють з різними типами вводу та локалями. Ретельно тестуйте свої компоненти з різними мовами та методами вводу.
3. Розмітки справа наліво (RTL)
Якщо ваш застосунок підтримує мови з напрямком письма справа наліво (наприклад, арабська, іврит), переконайтеся, що ваші маніпуляції з DOM за допомогою рефів враховують зворотну розмітку. Наприклад, при анімації елементів, розгляньте можливість зміни напрямку анімації для RTL-мов.
4. Аспекти продуктивності
Хоча рефи надають потужний спосіб взаємодії з DOM, надмірне їх використання може призвести до проблем з продуктивністю. Пряма маніпуляція DOM оминає віртуальний DOM React та процес узгодження, що потенційно може призвести до невідповідностей та повільніших оновлень. Використовуйте рефи розсудливо і тільки тоді, коли це необхідно.
Висновок
Рефи в React, зокрема useRef
та createRef
, є важливими інструментами для розробників React. Розуміння нюансів кожного підходу та коли їх ефективно застосовувати є вирішальним для створення надійних та продуктивних застосунків. createRef
залишається стандартом для управління рефами в класових компонентах, гарантуючи, що кожен екземпляр має свій унікальний реф. useRef
, завдяки своїй здатності зберігатися між рендерами, є ідеальним для функціональних компонентів, пропонуючи спосіб керування DOM-елементами та збереження значень без ініціювання непотрібних повторних рендерів. Розумно використовуючи ці інструменти, ви можете покращити функціональність та користувацький досвід ваших застосунків на React, задовольняючи потреби глобальної аудиторії за допомогою доступних та продуктивних інтерфейсів.
Оскільки React продовжує розвиватися, оволодіння цими фундаментальними концепціями дозволить вам створювати інноваційні та зручні веб-досвіди, що виходять за межі географічних та культурних кордонів. Не забувайте надавати пріоритет доступності, інтернаціоналізації та продуктивності для створення справді глобальних застосунків.