Trong phần 8 này, chúng ta sẽ tìm hiểu cách sử dụng hook useId
useId
useId là một React Hook để tạo các ID duy nhất có thể được chuyển đến các thuộc tính trợ năng.
Cách sử dụng
const id = useId()
Hook này được sử dụng trong các trường hợp:
- Tạo ID duy nhất cho thuộc tính trợ năng
- Tạo ID cho một số yếu tố liên quan
- Chỉ định tiền tố chung cho tất cả ID được tạo
- Sử dụng cùng một tiền tố ID trên máy khách và máy chủ
Gọi useId ở đầu của components để tạo ID duy nhất:
import { useId } from 'react';
function PasswordField() {
const passwordHintId = useId();
// ...
Tuy nhiên, bạn không thể gọi nó bên trong vòng lặp hoặc điều kiện. Nếu bạn cần điều đó, hãy trích xuất một component mới và chuyển state vào đó.
Không nên sử dụng useId để tạo khóa trong danh sách. Khóa phải được tạo từ dữ liệu của bạn.
Ví dụ minh họa
1.Tạo ID duy nhất cho thuộc tính trợ năng
import { useId } from 'react';
function PasswordField() {
const passwordHintId = useId();
// ...
Sau đó, bạn có thể chuyển ID đã tạo cho các thuộc tính khác nhau:
<>
<input type="password" aria-describedby={passwordHintId} />
<p id={passwordHintId}>
</>
Các thuộc tính trợ năng HTML như “aria-descriptionby” cho phép bạn chỉ định rằng hai thẻ có liên quan với nhau. Ví dụ: bạn có thể chỉ định rằng một phần tử (như input) được mô tả bởi một phần tử khác (như thẻ p).
<label>
Password:
<input type="password" aria-describedby="password-hint"/>
</label>
<p id="password-hint">
The password should contain at least 18 characters
</p>
Tuy nhiên, các ID mã hóa cứng như thế này không phải là cách làm tốt trong React. Một thành phần có thể được hiển thị nhiều lần trên trang—nhưng ID phải là duy nhất! Thay vì mã hóa cứng ID, hãy tạo một ID duy nhất với useId:
import { useId } from "react";
function PasswordField() {
const passwordHintId = useId();
return (
<>
< p id={passwordHintId}>The password should contain at least 18 characters</p >
</>
);
}
Giờ đây, ngay cả khi Password Field xuất hiện nhiều lần trên màn hình, các ID được tạo sẽ không xung đột.
import { useId } from 'react';
function PasswordField() {
const passwordHintId = useId();
return (
<>
Password:
< input type="password" aria-describedby={passwordHintId} />
< p id={passwordHintId}>
The password should contain at least 18 characters
);
}
export default function App() {
return (
<h2>Choose password</h2>
<PasswordField/>
<h2>Confirm password</h2>
<PasswordField/>
);
}
Đây là kết quả bạn sẽ nhìn thấy ở màn hình
Với sever rendering, useId yêu cầu một cây component giống hệt nhau trên serer và client. Nếu cây bạn hiển thị trên serer và client không khớp chính xác thì ID được tạo sẽ không khớp.
Tại sao useId tốt hơn bộ đếm tăng dần?
Bạn có thể thắc mắc tại sao useId lại tốt hơn việc tăng một biến toàn cục như nextId++.
Lợi ích chính của useId là React đảm bảo rằng nó hoạt động với server rendering. Trong quá trình server rendering, các component của bạn tạo ra đầu ra HTML. Sau đó, trên client, quá trình chuyển hóa sẽ gắn trình xử lý sự kiện của bạn vào HTML được tạo. Để quá trình chuyển hóa hoạt động, đầu ra của client phải khớp với HTML của server.
Điều này rất khó đảm bảo với bộ đếm tăng dần vì thứ tự mà Components của client được chuyển hóa có thể không khớp với thứ tự mà HTML server được phát ra. Bằng cách gọi useId, bạn đảm bảo rằng quá trình chuyển hóa sẽ hoạt động và đầu ra sẽ khớp giữa server và client.
Bên trong React, useId được tạo từ “đường dẫn gốc” của các component đang được gọi. Đây là lý do tại sao, nếu cây client và cây server giống nhau thì “đường dẫn gốc” sẽ khớp với nhau bất kể thứ tự hiển thị.
ví dụ 2: Tạo ID cho một số yếu tố liên quan
Nếu bạn cần cung cấp ID cho nhiều thành phần liên quan, bạn có thể gọi useId để tạo tiền tố chung cho chúng:
import { useId } from 'react';
export default function Form() {
const id = useId();
return (
First Name:
< input id={id + '-firstName'} type="text" />
Last Name:
< input id={id + '-lastName'} type="text" />
);
}
Đây là kết quả hiển thị trên màn hình
Ví dụ 3: Chỉ định tiền tố chung cho tất cả ID được tạo
Nếu bạn hiển thị nhiều ứng dụng React độc lập trên một trang duy nhất, hãy chuyển định danh Prefix dưới dạng tùy chọn cho lệnh gọi “createRoot” hoặc “HydraRoot” của bạn. Điều này đảm bảo rằng các ID do hai ứng dụng khác nhau tạo ra không bao giờ xung đột vì mọi số nhận dạng được tạo bằng useId sẽ bắt đầu bằng tiền tố riêng biệt mà bạn đã chỉ định.
import { createRoot } from 'react-dom/client';
import App from './App.js';
import './styles.css';
const root1 = createRoot(document.getElementById('root1'), {
identifierPrefix: 'my-first-app-'
});
root1.render();
const root2 = createRoot(document.getElementById('root2'), {
identifierPrefix: 'my-second-app-'
});
root2.render();
Đây là kết quả trên màn hình: