useId
useId — хук React для генерацыі ўнікальных ідэнтыфікатараў, якія далей можна выкарыстоўваць у атрыбутах даступнасці.
const id = useId()Апісанне
useId()
Выклічце useId на верхнім узроўні вашага кампанента, каб згенераваць унікальны ідэнтыфікатар:
import { useId } from 'react';
function PasswordField() {
const passwordHintId = useId();
// ...Болей прыкладаў глядзіце ніжэй.
Параметры
useId не прымае аніякіх параметраў.
Значэнні, якія вяртаюцца
useId вяртае радок з унікальным ідэнтыфікатарам, які звязаны з гэтым канкрэтным выклікам useId у гэтым канкрэтным кампаненце.
Агаворкі
useId— хук, а значыць, вы можаце выклікаць яго толькі на верхнім узроўні вашага кампанента ці ўнутры ўласнага хука. Ëн не можа быць выкліканы ўнутры цыкла альбо ўмовы. Калі вам усё ж гэта патрэбна, то стварыце новы кампанент і перанясіце стан туды.useIdне мусіць выкарыстоўвацца для генерацыі ключоў кэша для use(). Ідэнтыфікатар стабільны пры манціраванні, але можа змяняцца паміж рэндарамі. Ключы кэша мусяць генерыравацца на падставе вашых даных.useIdне мусіць выкарыстоўвацца для генерацыі ключоў у спісах. Ключы мусяць генерыравацца на падставе вашых даных.useIdна дадзены момант не можа быць выкарыстаны ўнутры асінхронных серверных кампанентаў.
Выкарыстанне
Генерацыя ўнікальных ідэнтыфікатараў для атрыбутаў даступнасці
Выклічце useId на верхнім узроўні вашага кампанента каб згенераваць унікальны ідэнтыфікатар:
import { useId } from 'react';
function PasswordField() {
const passwordHintId = useId();
// ...Далей вы можаце перадаць згенераваны ідэнтыфікатар у розныя атрыбуты:
<>
<input type="password" aria-describedby={passwordHintId} />
<p id={passwordHintId}>
</>Давайце разгледзім прыклад, калі гэта можа быць карысна.
Атрыбуты даступнасці ў HTML як, напрыклад, aria-describedby дазваляюць пазначыць, што два тэгі звязаныя адзін з адным. Такім чынам, як варыянт, вы можаце адзначыць, што элемент (напрыклад, поле ўводу) апісаны іншым элементам (напрыклад, параграфам).
У звычайным HTML, вы б апісалі гэта так:
<label>
Пароль:
<input
type="password"
aria-describedby="password-hint"
/>
</label>
<p id="password-hint">
Пароль мусіць змяшчаць як мінімум 18 сімвалаў
</p>Але ўказанне ідэнтыфікатара наўпрост у кодзе не з’яўляецца добрай практыкай у React. На старонцы кампанент можа быць адрэндараны болей за адзін раз, а ідэнтыфікатары павінны быць унікальнымі! Замест указання пастаяннага ідэнтыфікатара, згенеруйце ўнікальны з дапамогай useId:
import { useId } from 'react';
function PasswordField() {
const passwordHintId = useId();
return (
<>
<label>
Пароль:
<input
type="password"
aria-describedby={passwordHintId}
/>
</label>
<p id={passwordHintId}>
Пароль мусіць змяшчаць як мінімум 18 сімвалаў
</p>
</>
);
}Цяпер, нават калі PasswordField з’явіцца на старонцы некалькі разоў, згенераваныя ідэнтыфікатары не будуць канфліктаваць.
import { useId } from 'react'; function PasswordField() { const passwordHintId = useId(); return ( <> <label> Пароль: <input type="password" aria-describedby={passwordHintId} /> </label> <p id={passwordHintId}> Пароль мусіць змяшчаць як мінімум 18 сімвалаў </p> </> ); } export default function App() { return ( <> <h2>Прыдумайце пароль</h2> <PasswordField /> <h2>Пацвердзіце пароль</h2> <PasswordField /> </> ); }
Азнаёмцеся з відэа, каб убачыць розніцу ў карыстальніцкім досведзе пры выкарыстанні дапаможных тэхналогій.
Deep Dive
Вы можаце задумацца: чаму useId лепей за інкрэментальную глабальную пераменную накшталт nextId++.
Асноўная перавага useId у тым, што React забяспечвае працу пры серверным рэндарынгу. Падчас сервернага рэндарынгу, з вашых кампанентаў генеруецца HTML. Потым, на кліенце, падчас гідратацыі адбываецца прывязка апрацоўшчыкаў падзей да згенераванага HTML. Каб гідратацыя спрацавала, вынік кліента мусіць супадаць з HTML сервера.
Гэта вельмі цяжка гарантаваць праз інкрэментальны лічыльнік, бо парадак, у якім кліент робіць гідратацыю кампанентаў, можа не адпавядаць парадку, у якім сервер складае HTML. Карыстаючыся useId, можна гарантаваць, што гідрадацыя спрацуе, і вынік будзе аднолькавым і на серверы, і кліенце.
Унутры React, useId генеруецца на падставе размяшчэння бацькоўскага кампанента». Менавіта таму, калі дрэвы кліента і сервера ідэнтычныя, «размяшчэнне бацькоўскага кампанента» будзе супадаць незалежна ад парадку рэндара.
Генерацыя ідэнтыфікатараў для некалькі звязаных элементаў
Калі вам трэба даць ідэнтыфікатары некалькім звязаным элементам, вы можаце выкарыстаць useId каб згенераваць агульны прэфікс для іх:
import { useId } from 'react'; export default function Form() { const id = useId(); return ( <form> <label htmlFor={id + '-firstName'}>Імя:</label> <input id={id + '-firstName'} type="text" /> <hr /> <label htmlFor={id + '-lastName'}>Прозвішча:</label> <input id={id + '-lastName'} type="text" /> </form> ); }
Гэта дазволіць вам пазбегнуць выклікаў useId для кожнага элемента, які патрабуе ўнікальны ідэнтыфікатар.
Вызначэнне агульнага прэфікса для ўсіх згенераваных ідэнтыфікатараў
Калі вы рэндарыце некалькі незалежных праграм React на адной старонцы, перадайце identifierPrefix у опцыях да вашых выклікаў createRoot ці hydrateRoot. Гэта гарантуе, што ідэнтыфікатары з дзвюх розных праграм не будуць канфліктаваць, бо кожны згенераваны праз useId ідэнтыфікатар будзе пачынацца з адрознага прэфікса, які вы ўказалі.
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 />);
Выкарыстанне аднолькавых прэфіксаў для ідэнтыфікатараў на кліенце і на серверы
Калі вы рэндарыце некалькі незалежных праграм React на адной старонцы, і некаторыя з гэтых праграм рэндарацца на серверы, пераканайцеся, што identifierPrefix, які вы перадаяце ў выклік hydrateRoot на кліенце, ідэнтычны identifierPrefix, які вы перадаяце праз API сервера, такія як 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' }
);У identifierPrefix няма патрэбы, калі вы маеце толькі адну праграму React на старонцы.