Skip to content

Latest commit

 

History

History
334 lines (249 loc) · 13.5 KB

File metadata and controls

334 lines (249 loc) · 13.5 KB
title useId

useId — хук React для генерацыі ўнікальных ідэнтыфікатараў, якія далей можна выкарыстоўваць у атрыбутах даступнасці.

const id = useId()

Апісанне {/reference/}

useId() {/useid/}

Выклічце useId на верхнім узроўні вашага кампанента, каб згенераваць унікальны ідэнтыфікатар:

import { useId } from 'react';

function PasswordField() {
  const passwordHintId = useId();
  // ...

Болей прыкладаў глядзіце ніжэй.

Параметры {/parameters/}

useId не прымае аніякіх параметраў.

Значэнні, якія вяртаюцца {/returns/}

useId вяртае радок з унікальным ідэнтыфікатарам, які звязаны з гэтым канкрэтным выклікам useId у гэтым канкрэтным кампаненце.

Агаворкі {/caveats/}

  • useId — хук, а значыць, вы можаце выклікаць яго толькі на верхнім узроўні вашага кампанента ці ўнутры ўласнага хука. Ëн не можа быць выкліканы ўнутры цыкла альбо ўмовы. Калі вам усё ж гэта патрэбна, то стварыце новы кампанент і перанясіце стан туды.
  • useId не мусіць выкарыстоўвацца для генерацыі ключоў кэша для use(). Ідэнтыфікатар стабільны пры манціраванні, але можа змяняцца паміж рэндарамі. Ключы кэша мусяць генерыравацца на падставе вашых даных.
  • useId не мусіць выкарыстоўвацца для генерацыі ключоў у спісах. Ключы мусяць генерыравацца на падставе вашых даных.
  • useId на дадзены момант не можа быць выкарыстаны ўнутры асінхронных серверных кампанентаў.

Выкарыстанне {/usage/}

Не выкарыстоўвайце useId для генерацыі ключоў у спісах. Ключы мусяць генерыравацца на падставе вашых даных.

### Генерацыя ўнікальных ідэнтыфікатараў для атрыбутаў даступнасці {/*generating-unique-ids-for-accessibility-attributes*/}

Выклічце 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 лепей за інкрэментальны лічыльнік? {/why-is-useid-better-than-an-incrementing-counter/}

Вы можаце задумацца: чаму 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 на старонцы.