React 生成传递给无障碍属性的唯一 ID

useId()

在组件的顶层调用 useId 生成唯一 ID:

js 复制代码
import { useId } from 'react';  

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

useId 不带任何参数。

返回值

useId 返回一个唯一的字符串 ID,与此特定组件中的 useId 调用相关联。

注意事项
  • useId 是一个 Hook,因此你只能 在组件的顶层 或自己的 Hook 中调用它。你不能在内部循环或条件判断中调用它。如果需要,可以提取一个新组件并将 state 移到该组件中。
  • useId 不应该被用来生成列表中的 keykey 应该由你的数据生成

用法

为无障碍属性生成唯一 ID

在组件的顶层调用 useId 生成唯一 ID:

复制代码
import { useId } from 'react';

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

你可以将 生成的 ID 传递给不同的属性:

复制代码
<>
  <input type="password" aria-describedby={passwordHintId} />
  <p id={passwordHintId}>
</>

让我们通过一个例子,看看这个什么时候有用

aria-describedby 这样的 HTML 无障碍属性 允许你指定两个标签之间的关系。例如,你可以指定一个元素(比如输入框)由另一个元素(比如段落)描述。

在常规的 HTML 中,你会这样写:

复制代码
<label>
  密码:
  <input
    type="password"
    aria-describedby="password-hint"
  />

</label>
<p id="password-hint">
  密码应该包含至少 18 个字符
</p>

然而,在 React 中直接编写 ID 并不是一个好的习惯。一个组件可能会在页面上渲染多次,但是 ID 必须是唯一的!不要使用自己编写的 ID,而是使用 useId 生成唯一的 ID。

复制代码
import { useId } from 'react';

function PasswordField() {
  const passwordHintId = useId();
  
  return (
    <>
      <label>
        密码:
        <input
          type="password"
          aria-describedby={passwordHintId}
        />
      </label>
      <p id={passwordHintId}>
        密码应该包含至少 18 个字符
      </p>
    </>
  );
}

现在,即使 PasswordField 多次出现在屏幕上,生成的 ID 并不会冲突。

js 复制代码
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 />
    </>
  );
}

为多个相关元素生成 ID

如果你需要为多个相关元素生成 ID,可以调用 useId 来为它们生成共同的前缀:

js 复制代码
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>
  );
}

可以使你避免为每个需要唯一 ID 的元素调用 useId


为所有生成的 ID 指定共享前缀

如果你在单个页面上渲染多个独立的 React 应用程序,请在 createRoothydrateRoot 调用中将 identifierPrefix 作为选项传递。这确保了由两个不同应用程序生成的 ID 永远不会冲突,因为使用 useId 生成的每个 ID 都将以你指定的不同前缀开头。

index.html

js 复制代码
<!DOCTYPE html>
<html>
  <head><title>My app</title></head>
  <body>
    <div id="root1"></div>
    <div id="root2"></div>
  </body>
</html>

App.js

js 复制代码
import { useId } from 'react';

function PasswordField() {
  const passwordHintId = useId();
  console.log('生成的 ID:', passwordHintId)
  return (
    <>
      <label>
        密码:
        <input
          type="password"
          aria-describedby={passwordHintId}
        />
      </label>
      <p id={passwordHintId}>
        密码应该包含至少 18 个字符
      </p>
    </>
  );
}

export default function App() {
  return (
    <>
      <h2>输入密码</h2>
      <PasswordField />
    </>
  );
}

index.js

js 复制代码
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 />);

useId -- React 中文文档 (docschina.org)

相关推荐
qq_422152571 分钟前
PDF页面管理的几种实用方法:拆分、合并、删除指定页面
java·前端·pdf
触底反弹5 分钟前
💥 暴力解 LeetCode 导致 OOM:10000 行数据撑爆 V8 堆内存的完整排查
javascript·算法·面试
小小测试开发5 分钟前
Midscene.js:14K Stars 视驱 UI 自动化框架,用截图替代 DOM 选择器写测试
javascript·ui·自动化
qq_212838976 分钟前
后端Node.js + MySQL,前端Html+js,Nginx反向代理快速部署WEB项目
前端·mysql·node.js
Mh9 分钟前
程序员和非程序员使用 AI 进行编程的区别究竟在哪里?
前端·javascript·xcode
谭光志8 小时前
Vibe Coding 时代,程序员该何去何从
前端·后端·ai编程
仿生狮子10 小时前
别再说“全栈”了,AI 时代团队只认这 5 种人
前端·人工智能·后端
kyriewen10 小时前
AI 写的 React 组件,合并前必查的 6 个坏味道——每个都有代码对比
前端·javascript·react.js
Highcharts.js11 小时前
软件开发公司为什么选择 Highcharts?
前端·前端框架·echarts·数据可视化·技术选型·highcharts·图表工具
多加点辣也没关系11 小时前
JavaScript|第13章:原始类型的方法
开发语言·javascript·ecmascript