| title | useId |
|---|
useId — хук React для генерацыі ўнікальных ідэнтыфікатараў, якія далей можна выкарыстоўваць у атрыбутах даступнасці.
const id = useId()Выклічце useId на верхнім узроўні вашага кампанента, каб згенераваць унікальны ідэнтыфікатар:
import { useId } from 'react';
function PasswordField() {
const passwordHintId = useId();
// ...Болей прыкладаў глядзіце ніжэй.
useId не прымае аніякіх параметраў.
useId вяртае радок з унікальным ідэнтыфікатарам, які праасацыяваны з гэтым канкрэтным выклікам useId у гэтым канкрэтным кампаненце.
useId— хук, а значыць, вы можаце яго выклікаць толькі на верхнім узроўні вашага кампанента ці ўнутры ўласнага хука. Ëн не можа быць выкліканы ўнутры цыкла альбо ўмовы. Калі вы гэтага патрабуеце, выміце ў новы кампанент і перанясіце стан туды.useIdне мусіць быць выкарыстаны для генерацыі ключоў кэша для use(). Ідэнтыфікатар стабільны пакуль кампанент прымантаваны, але можа змяняцца паміж рэндарамі. Ключы кэша мусяць быць згенераванымі на падставе вашых даных.useIdне мусіць быць выкарыстаны для генерацыі ключоў у спісах. Ключы мусяць быць згенераванымі на падставе вашых даных.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 />
</>
);
}input { margin: 5px; }Азнаёмцеся з відэа, каб пабачыць розніцу ў карыстанні з ужываннем дапаможных тэхналогій.
Пры серверным рэндарынгу, useId патрабуе ідэнтычнага дрэва кампанентаў на серверы і на кліенце. Калі дрэвы, што вы рэндарыце і кліенце і серверы не суадносяцца, згенераваныя ідэнтыфікатары будуць адрознымі.
Вы можаце задумацца: чым useId лепей за нарастальную глабальную пераменную накшталт nextId++.
Асноўная перавага useId у тым, што React забяспечваю працу пры серверным рэндарынгу. Падчас сервернага рэндарынгу, з вашых кампанентаў генеруецца HTML. Потым, на кліенце, падчас гідратацыі адбываецца прывязка апрацоўшчыкаў падзей да згенераванага HTML. Каб гідратацыя спрацавала, вынік кліента мусіць супадаць з HTML сервера.
Гэта вельмі складана гарантаваць праз нарастальны лічыльнік, бо парадак, у якім кліент робіць гідратацыю кампанентаў, можа не адпавядаць парадку, у якім сервер складае HTML. Карыстаючыся useId, можна гарантаваць, што гідрадацыя спрацуе, і вынік будзе аднолькавым на серверы і кліенце.
Унутры React, useId генеруецца на падставе размяшчэння бацькоўскага кампанента». Менавіта таму, калі дрэвы кліента і сервера ідэнтычныя, «размяшчэнне бацькоўскага кампанента» будзе адпавядаць незалежна ад парадку рэндара.
Генерацыя ідэнтыфікатараў для некалькі звязаных элементаў {/generating-ids-for-several-related-elements/}
Калі вам трэба даць ідэнтыфікатары некалькім звязаным элементам, вы можаце выкарыстаць 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>
);
}input { margin: 5px; }Гэта дазволіць вам пазбегнуць выклікаў useId для кожнага элемента, які патрабуе ўнікальны ідэнтыфікатар.
Вызначэнне агульнага прэфікса для ўсіх згенераваных ідэнтыфікатараў {/specifying-a-shared-prefix-for-all-generated-ids/}
Калі вы рэндарыце некалькі незалежных праграм React на адной старонцы, перадайце identifierPrefix у опцыях да вашых выклікаў createRoot ці hydrateRoot. Гэта гарантуе, што ідэнтыфікатары з дзвюх розных праграм не будуць канфліктаваць, бо кожны згенераваны праз useId ідэнтыфікатар будзе пачынацца з адрознага прэфікса, які вы ўказалі.
<!DOCTYPE html>
<html>
<head><title>Мая праграма</title></head>
<body>
<div id="root1"></div>
<div id="root2"></div>
</body>
</html>import { useId } from 'react';
function PasswordField() {
const passwordHintId = useId();
console.log('Згенераваны ідэнтыфікатар:', passwordHintId)
return (
<>
<label>
Пароль:
<input
type="password"
aria-describedby={passwordHintId}
/>
</label>
<p id={passwordHintId}>
Пароль мусіць змяшчаць як найменш 18 сімвалаў
</p>
</>
);
}
export default function App() {
return (
<>
<h2>Прыдумайце пароль</h2>
<PasswordField />
</>
);
}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 />);#root1 {
border: 5px solid blue;
padding: 10px;
margin: 5px;
}
#root2 {
border: 5px solid green;
padding: 10px;
margin: 5px;
}
input { margin: 5px; }Выкарыстанне аднолькавых прэфіксаў для ідэнтыфікатараў на кліенце і на серверы {/using-the-same-id-prefix-on-the-client-and-the-server/}
Калі вы рэндарыце некалькі незалежных праграм 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 на старонцы.