useId
useId
adalah React Hook untuk menghasilkan ID unik yang dapat diteruskan ke atribut aksesibilitas.
const id = useId()
Referensi
useId()
Panggil useId
di tingkat teratas komponen Anda untuk menghasilkan ID unik:
import { useId } from 'react';
function PasswordField() {
const passwordHintId = useId();
// ...
Lihat lebih banyak contoh di bawah ini.
Parameter
useId
tidak mengambil parameter apapun.
Kembalian
useId
mengembalikan string ID unik yang terkait dengan panggilan useId
tertentu dalam komponen khusus ini.
Caveats
-
useId
adalah sebuah Hook, jadi Anda hanya dapat memanggilnya di tingkat teratas komponen Anda atau Hook Anda sendiri. Anda tidak dapat memanggilnya di dalam perulangan (loops) atau kondisi (conditions). Jika Anda membutuhkannya, ekstrak komponen baru dan pindahkan state ke dalamnya. -
useId
tidak boleh digunakan untuk menghasilkan key dalam daftar. Key harus dihasilkan dari data Anda.
Pengunaan
Menghasilkan ID unik untuk atribut aksesibilitas
Panggil useId
di tingkat atas komponen Anda untuk menghasilkan ID unik:
import { useId } from 'react';
function PasswordField() {
const passwordHintId = useId();
// ...
Anda kemudian dapat meneruskan ID yang dihasilkan ke atribut yang berbeda:
<>
<input type="password" aria-describedby={passwordHintId} />
<p id={passwordHintId}>
</>
Mari telusuri contoh untuk melihat kapan ini berguna.
Atribut aksesibilitas HTML seperti aria-describedby
membiarkan Anda menentukan bahwa dua tag terkait satu sama lain. Misalnya, Anda dapat menentukan bahwa suatu elemen (seperti sebuah masukan (input
)) dijelaskan oleh elemen lain (seperti sebuah paragraf (p
)).
Dalam HTML biasa, Anda akan menulisnya seperti ini:
<label>
Password:
<input
type="password"
aria-describedby="password-hint"
/>
</label>
<p id="password-hint">
The password should contain at least 18 characters
</p>
Namun, menuliskan ID secara langsung di dalam kode (hardcoding) seperti ini bukanlah praktik yang baik di React. Sebuah komponen dapat di-render lebih dari sekali pada halaman—namun ID harus unik! Alih-alih melakukan pemaksaan ID, buat ID unik dengan useId
:
import { useId } from 'react';
function PasswordField() {
const passwordHintId = useId();
return (
<>
<label>
Password:
<input
type="password"
aria-describedby={passwordHintId}
/>
</label>
<p id={passwordHintId}>
The password should contain at least 18 characters
</p>
</>
);
}
Sekarang, meskipun PasswordField
muncul beberapa kali di layar, ID yang dihasilkan tidak akan berbenturan.
import { useId } from 'react'; function PasswordField() { const passwordHintId = useId(); return ( <> <label> Password: <input type="password" aria-describedby={passwordHintId} /> </label> <p id={passwordHintId}> The password should contain at least 18 characters </p> </> ); } export default function App() { return ( <> <h2>Choose password</h2> <PasswordField /> <h2>Confirm password</h2> <PasswordField /> </> ); }
Tonton video ini untuk melihat perbedaan pengalaman pengguna dengan teknologi bantu.
Pendalaman
Anda mungkin bertanya-tanya mengapa useId
lebih baik daripada menambahkan variabel global seperti nextId++
.
Manfaat utama useId
adalah React memastikan bahwa ia bekerja dengan server rendering. Selama server rendering, komponen Anda menghasilkan keluaran HTML. Kemudian, pada klien, hidrasi melampirkan event handler Anda ke HTML yang dihasilkan. Agar hidrasi berfungsi, output klien harus cocok dengan HTML dari server.
Hal ini sangat sulit untuk dijamin dengan penghitung kenaikan karena urutan di mana komponen klien terhidrasi mungkin tidak sesuai dengan urutan di mana HTML dari server dipancarkan. Dengan memanggil useId
, Anda memastikan bahwa hidrasi akan berfungsi, dan hasilnya akan cocok antara server dan klien.
Di dalam React, useId
dihasilkan dari “jalur induk” dari komponen pemanggil. Inilah sebabnya, jika pohon di klien dan server sama, “jalur induk” akan cocok terlepas dari urutan rendering.
Menghasilkan ID untuk beberapa elemen terkait
Jika Anda perlu memberikan ID ke beberapa elemen terkait, Anda dapat memanggil useId
untuk menghasilkan awalan bersama untuk mereka:
import { useId } from 'react'; export default function Form() { const id = useId(); return ( <form> <label htmlFor={id + '-firstName'}>First Name:</label> <input id={id + '-firstName'} type="text" /> <hr /> <label htmlFor={id + '-lastName'}>Last Name:</label> <input id={id + '-lastName'} type="text" /> </form> ); }
Ini memungkinkan Anda menghindari pemanggilan useId
untuk setiap elemen yang membutuhkan ID unik.
Menentukan awalan bersama untuk semua ID yang dihasilkan
Jika Anda me-render beberapa aplikasi React independen pada satu halaman, berikan identifierPrefix
sebagai opsi untuk panggilan createRoot
atau hydrateRoot
Anda. Hal ini memastikan bahwa ID yang dihasilkan oleh dua aplikasi berbeda tidak pernah berbenturan karena setiap pengenal yang dibuat dengan useId
akan dimulai dengan awalan berbeda yang telah Anda tentukan.
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(<App />); const root2 = createRoot(document.getElementById('root2'), { identifierPrefix: 'my-second-app-' }); root2.render(<App />);
Using the same ID prefix on the client and the server
If you render multiple independent React apps on the same page, and some of these apps are server-rendered, make sure that the identifierPrefix
you pass to the hydrateRoot
call on the client side is the same as the identifierPrefix
you pass to the server APIs such as renderToPipeableStream
.
// Server
import { renderToPipeableStream } from 'react-dom/server';
const { pipe } = renderToPipeableStream(
<App />,
{ identifierPrefix: 'react-app1' }
);
// Client
import { hydrateRoot } from 'react-dom/client';
const domNode = document.getElementById('root');
const root = hydrateRoot(
domNode,
reactNode,
{ identifierPrefix: 'react-app1' }
);
You do not need to pass identifierPrefix
if you only have one React app on the page.