【React】useId

在 React 中,useId 是 React 18 引入的一个 Hook,用于生成一个在组件生命周期中保持稳定的唯一 ID。它主要用于:

  • 无障碍(accessibility)场景 ,比如表单控件需要一个 id 和 label 的 htmlFor 属性配对。
  • 服务端渲染(SSR) 与客户端渲染保持一致。
  • 避免多个组件生成的 ID 冲突。

🧠 为什么不用自己写 id?

以前开发者会自己写逻辑生成 id,比如用 Math.random()、Date.now() 或 uuid 生成,但这些在服务端渲染(SSR)和客户端渲染中可能不一致,从而导致 水合(hydration)错误。

SSR:服务端渲染出 html 内容,发给浏览器,浏览器接收到 html,先展示静态内容,然后加载动态js,就是将html激活(水合),然后就生成了动态应用,但是这样服务端和浏览器端的 id 生成就会不同(可能随机数生成等等)。


✅ useId 的基本语法

jsx 复制代码
const id = useId();
  • id 是一个 字符串,React 会自动加前缀,确保唯一性。

🧪 示例:表单中 label 与 input 关联

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

function NameInput() {
  const id = useId();

  return (
    <div>
      <label htmlFor={id}>姓名:</label>
      <input id={id} type="text" />
    </div>
  );
}

在这个例子中:

  • label 的 htmlFor 和 input 的 id 使用同一个值。
  • useId() 保证了 ID 在每次渲染中一致,适用于 SSR。

🧩 示例:多个组件实例

jsx 复制代码
function InputField({ label }) {
  const id = useId();

  return (
    <div>
      <label htmlFor={id}>{label}</label>
      <input id={id} type="text" />
    </div>
  );
}

function Form() {
  return (
    <>
      <InputField label="用户名" />
      <InputField label="邮箱" />
    </>
  );
}

每个 InputField 都会生成不同的 id,即使组件重复使用也不会冲突。


⚠️ 注意事项

  1. useId 不能用在事件处理函数或条件判断内部。
  2. 它不能替代 key、uuid 等复杂 ID 生成需求(比如数据库 ID)。
  3. 如果你要生成 带后缀的 ID,可以这样做:
jsx 复制代码
const id = useId();
<input id={`${id}-email`} />

🎯 适用场景总结

场景 是否推荐用 useId
label 与 input/textarea 等的 ID 配对 ✅ 是
ARIA 属性如 aria-labelledby ✅ 是
SSR 页面保持一致性 ✅ 是
用于生成数据库 ID、URL 等 ❌ 否

如果在使用 React 17 或更低版本,可以用第三方库如 uuid 或 nanoid 作为替代,但在 React 18+ 推荐用 useId 来保证一致性和性能。

相关推荐
奕鼎竜瑆4 小时前
Solid 前端响应式开发从零到精通
前端·人工智能
动恰客流统计4 小时前
景区客流统计怎么做?兼顾管控与运营的实施方案解析
大数据·前端·人工智能
派小心.5 小时前
A/B测试工具免费版够用吗?
前端·数据分析
前端snow6 小时前
ai agent --- redis 缓存
前端
duanshu_6 小时前
官网表单与下载异常怎么排查?五个环节定位故障
前端·自动化·flyweight
Zhou1411367 小时前
SpringBoot_03_Web开发
前端·spring boot·python
辻弋2017 小时前
【无标题】
大数据·服务器·前端·搜索引擎·开源软件
FluxArt7 小时前
GPT Image 2.5 中文提示词教程:Flux Art 可复用模板
前端·gpt·算法
搬砖的小码农_Sky8 小时前
AI Agent:Windows上Node.js安装后 npm -v报错
前端·npm·node.js·人机交互
计算机魔术师9 小时前
半年翻倍!OpenAI再融300亿,估值冲到1.4万亿
前端