Hướng dẫn toàn diện khám phá React Refs, tập trung vào useRef và createRef. Tìm hiểu cách và thời điểm sử dụng từng loại để quản lý thành phần hiệu quả và truy cập DOM trong các ứng dụng toàn cầu.
React Refs: Giải mã useRef so với createRef
Trong thế giới phát triển React năng động, việc quản lý hiệu quả trạng thái thành phần và tương tác với Document Object Model (DOM) là rất quan trọng. React Refs cung cấp một cơ chế để truy cập và thao tác trực tiếp các phần tử DOM hoặc các thành phần React. Hai phương pháp chính để tạo Refs là useRef
và createRef
. Mặc dù cả hai đều phục vụ mục đích tạo Refs, nhưng chúng khác nhau về cách triển khai và trường hợp sử dụng. Hướng dẫn này nhằm mục đích làm sáng tỏ hai phương pháp này, cung cấp sự rõ ràng về thời điểm và cách tận dụng từng phương pháp một cách hiệu quả trong các dự án React của bạn, đặc biệt khi phát triển cho đối tượng toàn cầu.
Tìm hiểu về React Refs
Ref (viết tắt của reference - tham chiếu) là một tính năng của React cho phép bạn truy cập trực tiếp một nút DOM hoặc một thành phần React. Điều này đặc biệt hữu ích khi bạn cần:
- Thao tác trực tiếp một phần tử DOM, chẳng hạn như tập trung vào một trường nhập liệu.
- Truy cập các phương thức hoặc thuộc tính của thành phần con.
- Quản lý các giá trị tồn tại giữa các lần render mà không gây ra render lại (tương tự như các biến instance trong các thành phần class).
Mặc dù React khuyến khích một cách tiếp cận khai báo, nơi giao diện người dùng được quản lý thông qua trạng thái và props, nhưng có những tình huống cần thao tác trực tiếp. Refs cung cấp một cách để thu hẹp khoảng cách giữa bản chất khai báo của React và các thao tác DOM mệnh lệnh.
createRef
: Cách tiếp cận Thành phần Class
createRef
là một phương thức được cung cấp bởi React. Nó chủ yếu được sử dụng trong các thành phần class để tạo Refs. Mỗi khi một thành phần class được khởi tạo, createRef
sẽ tạo một đối tượng Ref mới. Điều này đảm bảo rằng mỗi instance của thành phần có Ref duy nhất của riêng nó.
Cú pháp và Cách sử dụng
Để sử dụng createRef
, trước tiên bạn khai báo một Ref trong thành phần class của mình, thường là trong constructor. Sau đó, bạn gắn Ref vào một phần tử DOM hoặc một thành phần bằng thuộc tính ref
.
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.myRef = React.createRef();
}
componentDidMount() {
// Truy cập phần tử DOM sau khi thành phần được mount
this.myRef.current.focus();
}
render() {
return <input type="text" ref={this.myRef} />;
}
}
Trong ví dụ này, this.myRef
được tạo bằng React.createRef()
. Sau đó, nó được gán cho thuộc tính ref
của phần tử input. Sau khi thành phần được mount (trong componentDidMount
), bạn có thể truy cập nút DOM thực tế bằng this.myRef.current
và thực hiện các thao tác trên đó (trong trường hợp này, tập trung vào input).
Ví dụ: Tập trung vào một Trường Nhập liệu
Hãy xem xét một tình huống mà bạn muốn tự động tập trung vào một trường nhập liệu khi một thành phần được mount. Đây là một trường hợp sử dụng phổ biến cho Refs, đặc biệt là trong các biểu mẫu hoặc các phần tử tương tác.
class FocusInput extends React.Component {
constructor(props) {
super(props);
this.inputRef = React.createRef();
}
componentDidMount() {
this.inputRef.current.focus();
}
render() {
return (
<div>
<input type="text" ref={this.inputRef} />
</div>
);
}
}
Trong ví dụ này, FocusInput
tập trung vào trường nhập liệu ngay sau khi mount. Điều này có thể cải thiện trải nghiệm người dùng bằng cách hướng sự chú ý của người dùng đến phần tử input ngay khi thành phần được render.
Những Lưu ý Quan trọng với createRef
- Chỉ dành cho Thành phần Class:
createRef
được thiết kế để sử dụng trong các thành phần class. Mặc dù nó có thể hoạt động về mặt kỹ thuật trong các thành phần functional, nhưng đó không phải là mục đích sử dụng và có thể dẫn đến hành vi không mong muốn. - Ref Mới trên Mỗi Instance: Mỗi instance của một thành phần class sẽ có
createRef
riêng. Điều này rất quan trọng để duy trì sự cô lập giữa các instance thành phần.
useRef
: Hook Thành phần Functional
useRef
là một Hook được giới thiệu trong React 16.8. Nó cung cấp một cách để tạo các đối tượng Ref có thể thay đổi trong các thành phần functional. Không giống như createRef
, useRef
trả về cùng một đối tượng Ref mỗi khi thành phần render. Điều này làm cho nó trở nên lý tưởng để duy trì các giá trị giữa các lần render mà không kích hoạt render lại.
Cú pháp và Cách sử dụng
Sử dụng useRef
rất đơn giản. Bạn gọi Hook useRef
, chuyển một giá trị ban đầu. Hook trả về một đối tượng với thuộc tính .current
, sau đó bạn có thể sử dụng để truy cập và sửa đổi giá trị.
import React, { useRef, useEffect } from 'react';
function MyFunctionalComponent() {
const myRef = useRef(null);
useEffect(() => {
// Truy cập phần tử DOM sau khi thành phần được mount
if (myRef.current) {
myRef.current.focus();
}
}, []);
return <input type="text" ref={myRef} />;
}
Trong ví dụ này, useRef(null)
tạo một Ref với giá trị ban đầu là null
. Hook useEffect
được sử dụng để truy cập phần tử DOM sau khi thành phần được mount. Thuộc tính myRef.current
giữ tham chiếu đến phần tử input, cho phép bạn tập trung vào nó.
Ví dụ: Theo dõi Các Giá trị Prop Trước đó
Một trường hợp sử dụng mạnh mẽ cho useRef
là theo dõi giá trị trước đó của một prop. Vì những thay đổi đối với Refs không kích hoạt render lại, bạn có thể sử dụng chúng để lưu trữ các giá trị mà bạn muốn duy trì giữa các lần render mà không ảnh hưởng đến giao diện người dùng.
import React, { useRef, useEffect } from 'react';
function PreviousValueComponent({ value }) {
const previousValue = useRef();
useEffect(() => {
previousValue.current = value;
}, [value]);
return (
<div>
<p>Giá trị Hiện tại: {value}</p>
<p>Giá trị Trước đó: {previousValue.current}</p>
</div>
);
}
Trong ví dụ này, previousValue.current
lưu trữ giá trị trước đó của prop value
. Hook useEffect
cập nhật Ref bất cứ khi nào prop value
thay đổi. Điều này cho phép bạn so sánh giá trị hiện tại và trước đó, điều này có thể hữu ích để phát hiện các thay đổi hoặc triển khai hoạt ảnh.
Những Lưu ý Quan trọng với useRef
- Chỉ dành cho Thành phần Functional:
useRef
là một Hook và chỉ có thể được sử dụng trong các thành phần functional hoặc các Hook tùy chỉnh. - Tồn tại Giữa Các Lần Render: Hook
useRef
trả về cùng một đối tượng Ref trên mỗi lần render. Đây là chìa khóa cho khả năng duy trì các giá trị mà không kích hoạt render lại. - Thuộc tính
.current
Có thể Thay đổi: Bạn có thể sửa đổi trực tiếp thuộc tính.current
của đối tượng Ref. - Giá trị Ban đầu: Bạn có thể cung cấp một giá trị ban đầu cho
useRef
. Giá trị này sẽ được gán cho thuộc tính.current
khi thành phần được render lần đầu tiên. - Không Render lại: Sửa đổi thuộc tính
.current
của Ref không gây ra render lại thành phần.
useRef
so với createRef
: So sánh Chi tiết
Bây giờ chúng ta đã khám phá cả useRef
và createRef
một cách riêng lẻ, hãy so sánh chúng cạnh nhau để làm nổi bật những khác biệt chính của chúng và khi nào nên chọn cái nào hơn cái kia.
Tính năng | useRef |
createRef |
---|---|---|
Loại Thành phần | Thành phần Functional | Thành phần Class |
Hook hoặc Phương thức | Hook | Phương thức |
Instance Ref | Trả về cùng một đối tượng Ref trên mỗi lần render | Tạo một đối tượng Ref mới trên mỗi instance của thành phần |
Trường hợp Sử dụng |
|
|
Chọn Ref Phù hợp: Hướng dẫn Quyết định
Đây là một hướng dẫn đơn giản để giúp bạn chọn giữa useRef
và createRef
:
- Bạn có đang làm việc với một thành phần functional không? Sử dụng
useRef
. - Bạn có đang làm việc với một thành phần class không? Sử dụng
createRef
. - Bạn có cần duy trì một giá trị giữa các lần render mà không kích hoạt render lại không? Sử dụng
useRef
. - Bạn có cần theo dõi giá trị trước đó của một prop không? Sử dụng
useRef
.
Vượt ra ngoài Thao tác DOM: Các Trường hợp Sử dụng Nâng cao cho Refs
Mặc dù truy cập và thao tác các phần tử DOM là một trường hợp sử dụng chính cho Refs, nhưng chúng cung cấp những khả năng vượt ra ngoài chức năng cốt lõi này. Hãy khám phá một số kịch bản nâng cao trong đó Refs có thể đặc biệt hữu ích.
1. Truy cập Các Phương thức của Thành phần Con
Refs có thể được sử dụng để truy cập các phương thức được định nghĩa trong các thành phần con. Điều này cho phép một thành phần cha kích hoạt các hành động hoặc truy xuất dữ liệu trực tiếp từ các thành phần con của nó. Cách tiếp cận này đặc biệt hữu ích khi bạn cần kiểm soát chi tiết các thành phần con.
class ParentComponent extends React.Component {
constructor(props) {
super(props);
this.childRef = React.createRef();
}
handleClick = () => {
// Gọi một phương thức trên thành phần con
this.childRef.current.doSomething();
};
render() {
return (
<div>
<ChildComponent ref={this.childRef} />
<button onClick={this.handleClick}>Kích hoạt Hành động Con</button>
</div>
);
}
}
class ChildComponent extends React.Component {
doSomething = () => {
console.log('Hành động thành phần con đã được kích hoạt!');
};
render() {
return <div>Đây là một thành phần con.</div>;
}
}
Trong ví dụ này, ParentComponent
sử dụng một Ref để truy cập ChildComponent
và gọi phương thức doSomething
của nó.
2. Quản lý Tiêu điểm và Lựa chọn
Refs là vô giá để quản lý tiêu điểm và lựa chọn trong các trường nhập liệu và các phần tử tương tác khác. Điều này rất quan trọng để tạo ra các giao diện thân thiện với người dùng và dễ truy cập.
import React, { useRef, useEffect } from 'react';
function FocusOnMount() {
const inputRef = useRef(null);
useEffect(() => {
if (inputRef.current) {
inputRef.current.focus();
inputRef.current.select(); // Chọn văn bản trong input
}
}, []);
return <input type="text" ref={inputRef} defaultValue="Văn bản ban đầu" />;
}
Ví dụ này tập trung vào input và chọn văn bản của nó ngay khi thành phần được mount.
3. Tạo Hoạt ảnh cho Các Phần tử
Refs có thể được sử dụng kết hợp với các thư viện hoạt ảnh (như GreenSock hoặc Framer Motion) để thao tác trực tiếp DOM và tạo các hoạt ảnh phức tạp. Điều này cho phép kiểm soát chi tiết các chuỗi hoạt ảnh.
Ví dụ sử dụng JavaScript thuần túy để đơn giản:
import React, { useRef, useEffect } from 'react';
function AnimatedBox() {
const boxRef = useRef(null);
useEffect(() => {
const box = boxRef.current;
if (box) {
// Hoạt ảnh đơn giản: di chuyển hộp sang phải
box.animate(
[
{ transform: 'translateX(0)' },
{ transform: 'translateX(100px)' },
],
{
duration: 1000, // 1 giây
iterations: Infinity, // Lặp lại mãi mãi
direction: 'alternate',
}
);
}
}, []);
return <div ref={boxRef} style={{ width: '100px', height: '100px', backgroundColor: 'lightblue' }}></div>;
}
Ví dụ này sử dụng Web Animations API để tạo hoạt ảnh cho một hộp đơn giản, di chuyển nó qua lại theo chiều ngang.
Các Phương pháp hay nhất để Sử dụng React Refs trong Các Ứng dụng Toàn cầu
Khi phát triển các ứng dụng React cho đối tượng toàn cầu, điều quan trọng là phải xem xét cách Refs tương tác với quốc tế hóa (i18n) và bản địa hóa (l10n). Dưới đây là một số phương pháp hay nhất:
1. Khả năng truy cập (A11y)
Đảm bảo rằng việc sử dụng Refs của bạn không ảnh hưởng tiêu cực đến khả năng truy cập. Ví dụ: khi tập trung các phần tử theo chương trình, hãy xem xét thứ tự tiêu điểm của người dùng và liệu thay đổi tiêu điểm có phù hợp với trình đọc màn hình và người dùng bàn phím hay không.
import React, { useRef, useEffect } from 'react';
function AccessibleFocus() {
const buttonRef = useRef(null);
useEffect(() => {
const button = buttonRef.current;
if (button) {
// Chỉ tập trung nếu nút chưa được người dùng tập trung
if (document.activeElement !== button) {
button.focus();
}
}
}, []);
return <button ref={buttonRef}>Nhấp vào Tôi</button>;
}
2. Các Trường Nhập liệu Quốc tế hóa
Khi làm việc với các trường nhập liệu, hãy lưu ý đến các phương thức nhập liệu và bộ ký tự khác nhau được sử dụng trong các ngôn ngữ khác nhau. Đảm bảo rằng các thao tác dựa trên Ref của bạn (ví dụ: lựa chọn, vị trí con trỏ) hoạt động chính xác trên các loại nhập liệu và ngôn ngữ khác nhau. Kiểm tra kỹ lưỡng các thành phần của bạn với các ngôn ngữ và phương thức nhập liệu khác nhau.
3. Bố cục Từ phải sang trái (RTL)
Nếu ứng dụng của bạn hỗ trợ các ngôn ngữ RTL (ví dụ: tiếng Ả Rập, tiếng Do Thái), hãy đảm bảo rằng các thao tác DOM của bạn bằng Refs có tính đến bố cục đảo ngược. Ví dụ: khi tạo hoạt ảnh cho các phần tử, hãy cân nhắc đảo ngược hướng hoạt ảnh cho các ngôn ngữ RTL.
4. Cân nhắc về Hiệu suất
Mặc dù Refs cung cấp một cách mạnh mẽ để tương tác với DOM, nhưng việc lạm dụng có thể dẫn đến các vấn đề về hiệu suất. Thao tác DOM trực tiếp bỏ qua DOM ảo và quy trình hòa giải của React, có khả năng dẫn đến sự không nhất quán và cập nhật chậm hơn. Sử dụng Refs một cách thận trọng và chỉ khi cần thiết.
Kết luận
React Refs, cụ thể là useRef
và createRef
, là những công cụ thiết yếu cho các nhà phát triển React. Hiểu rõ sự khác biệt của từng cách tiếp cận và thời điểm áp dụng chúng một cách hiệu quả là rất quan trọng để xây dựng các ứng dụng mạnh mẽ và hiệu quả. createRef
vẫn là tiêu chuẩn để quản lý Refs trong các thành phần class, đảm bảo mỗi instance có Ref duy nhất của riêng nó. useRef
, với bản chất liên tục của nó giữa các lần render, là lý tưởng cho các thành phần functional, cung cấp một cách để quản lý các phần tử DOM và duy trì các giá trị mà không kích hoạt render lại không cần thiết. Bằng cách tận dụng các công cụ này một cách khôn ngoan, bạn có thể nâng cao chức năng và trải nghiệm người dùng của các ứng dụng React của mình, phục vụ đối tượng toàn cầu với các giao diện dễ truy cập và hiệu suất cao.
Khi React tiếp tục phát triển, việc nắm vững các khái niệm cơ bản này sẽ cho phép bạn tạo ra những trải nghiệm web sáng tạo và thân thiện với người dùng, vượt qua các ranh giới địa lý và văn hóa. Hãy nhớ ưu tiên khả năng truy cập, quốc tế hóa và hiệu suất để cung cấp các ứng dụng thực sự toàn cầu.