useId Hook — յուրահատուկ ID-ների ստեղծում SSR-ի և Accessibility-ի համար
React 18-ից սկսած ներկայացվեց նոր hook՝ useId, որը ստեղծում է ունիկալ, կայուն և կանխատեսելի ID։ Այն նախատեսված է այն դեպքերի համար, երբ քեզ պետք է ID, որը համընկնի server-side, որքան client-side rendering-ի ժամանակ։
Այս hook-ը հատկապես օգտակար է SSR նախագծերում (օր. Next.js), որտեղ React-ը նախ ստեղծում է HTML server-ում, հետո այն “rehydrate” է անում browser-ում։ Եթե ID-ները տարբեր լինեն երկու կողմում, React-ը կխախտի DOM-ի կապը։
🔹 Ինչ խնդիր է լուծում useId-ը
Ենթադրենք, մենք պետք է կապենք input-ը և label-ը՝ accessibility նպատակներով։ Դրա համար անհրաժեշտ է ունենալ եզակի ID յուրաքանչյուր input-ի համար։ Սակայն SSR նախագծերում եթե ID-ն գեներացվի պատահական թվով (օր. Math.random()), ապա այն կլինի տարբեր server-ում և client-ում՝ առաջացնելով զգուշացում.
Warning: Prop `id` did not match. Server: "input-17" Client: "input-83"
useId-ը ստեղծում է նույն ID-ն երկու կողմերում՝ ապահովելով կայունություն և կանխելով hydration խնդիրները։
📍 Օրինակ 1 — Label և Input կապ
import React, { useId } from 'react';
export default function NameField() {
const id = useId();
return (
<div>
<label htmlFor={id}>Անունը</label>
<input id={id} type="text" placeholder="Գրի՛ր քո անունը" />
</div>
);
}
Այստեղ React-ը ավտոմատ կստեղծի ID՝ օրինակ՝ react-1:0,
և նույն ID-ն կօգտագործվի թե server-side render-ի, թե client-side hydration-ի ժամանակ։
📍 Օրինակ 2 — Մի քանի input-ների յուրահատուկ ID-ներ
import React, { useId } from 'react';
export default function FormExample() {
const nameId = useId();
const emailId = useId();
return (
<form>
<div>
<label htmlFor={nameId}>Անուն</label>
<input id={nameId} type="text" />
</div>
<div>
<label htmlFor={emailId}>Էլ. փոստ</label>
<input id={emailId} type="email" />
</div>
</form>
);
}
Յուրաքանչյուր `useId()` կանչ ստեղծում է կայուն, եզակի ID, որը React-ը գեներացնում է իր ներքին հաշվարկով։ Այն ապահովում է՝ որ երբ rerender լինի կամ hydration, ID-ն նույնը կմնա։
📍 Օրինակ 3 — Նույն ID տարբեր կոմպոնենտներում (բազային ID + postfix)
Եթե ուզում ես մեկ `useId()` օգտագործել մի քանի տեղ՝ բայց տարբեր postfix-ներով, կարող ես անել այսպես․
import React, { useId } from 'react';
export default function RangeSlider() {
const baseId = useId();
return (
<div>
<label htmlFor={`${baseId}-min`}>Նվազագույն արժեք</label>
<input id={`${baseId}-min`} type="range" />
<label htmlFor={`${baseId}-max`}>Առավելագույն արժեք</label>
<input id={`${baseId}-max`} type="range" />
</div>
);
}
Այս մոտեցումը թույլ է տալիս մեկ բազային ID-ից ստեղծել մի քանի ենթա-ID, որոնք նույնպես կայուն կլինեն SSR-ում։
⚙️ Ինչ է վերադարձնում useId-ը
- Վերադարձնում է string, օրինակ՝
react-1:2 - React-ը երաշխավորում է դրա եզակիությունը նույն render tree-ի ներսում։
- React 18-ից սկսած՝ SSR-ն օգտագործում է նույն seed՝ նույն ID-ների consistency-ի համար։
📍 Օրինակ 4 — SSR-ում կայունություն (Next.js)
Երբ օգտագործում ես Next.js-ի նման framework, որը server-side render է անում React-ը, ID-ների կայունությունը դառնում է կարևոր։ useId-ը ապահովում է, որ server-ում և client-ում նույն ID-ն ստեղծվի։
// pages/index.js
import { useId } from 'react';
export default function Home() {
const id = useId();
return (
<div>
<label htmlFor={id}>Username</label>
<input id={id} type="text" />
</div>
);
}
Առանց useId-ի՝ server-ը և client-ը կստեղծեին տարբեր պատահական ID-ներ՝ առաջացնելով React hydration error։ useId-ի դեպքում դրանք 100% համընկնում են։
📘 Լավագույն պրակտիկաներ
- Մի օգտագործիր useId արժեքը որպես key — React-ը դա նախատեսել է միայն ID-ների համար։
- Օգտագործիր այն՝ երբ պետք է կապես label/input, aria-labelledby, կամ aria-describedby։
- Մի փորձիր ձևափոխել ID-ն ձեռքով՝ React-ը այն կառավարում է։
🎯 Վարժություն (փորձիր ինքդ)
Գրիր կոմպոնենտ, որը․
- Ունի երկու input դաշտ (անուն և email)։
- Յուրաքանչյուրին ստեղծիր եզակի ID `useId`-ով։
- Կապիր label-ը input-ի հետ `htmlFor`-ի միջոցով։
- Փորձիր SSR (Next.js) միջավայրում — React-ը չպետք է գանգատվի hydration-ի մասին։
📘 Ամփոփում
- useId — React 18-ից նոր hook է, որը ստեղծում է եզակի և կայուն ID-ներ։
- Օգտակար է SSR նախագծերում և accessibility նպատակներով։
- React-ը երաշխավորում է, որ server-side և client-side ID-ները նույնն են։
- Հարմար է label-input կապերի և aria հատկությունների համար։