useId
面试速答(30 秒版 TL;DR)
useId是 React 18 新增的 Hook,用来生成稳定且适合 SSR/CSR 对齐的唯一 ID。- 它最常见的用途是做无障碍关联,例如
label和input的id/htmlFor。 - 它不是列表 key 生成器,也不是数据库主键生成器。
- 核心价值是:避免服务端渲染和客户端 hydration 时 ID 不一致。
1. 为什么 React 18 需要它
在 SSR 场景里,如果你自己用:
Math.random()- 自增变量
Date.now()
生成 ID,服务端和客户端很可能不一致,导致 hydration 对不上。
useId 解决的是“同一组件树在服务端和客户端生成一致标识”的问题。
2. 基本用法
function Field() {
const id = useId()
return (
<>
<label htmlFor={id}>用户名</label>
<input id={id} />
</>
)
}
如果一个组件里有多组元素,可以在同一个前缀上拼接:
const id = useId()
const inputId = `${id}-input`
const hintId = `${id}-hint`
3. 它最适合的场景
3.1 可访问性(a11y)
label和inputaria-describedbyaria-labelledby
3.2 可复用组件库
组件库经常不能要求调用方手动传所有 DOM ID,这时 useId 很适合做内部关联。
4. 不适合的场景
4.1 列表 key
React 的 key 应该来自稳定业务标识,例如:
- 数据库 id
- 业务唯一字段
而不是 useId()。
4.2 数据持久化 ID
它只是 UI 层渲染时的稳定标识,不应用来当业务主键。
5. 面试高频答法
Q1:useId 和随机字符串有什么区别?
最大区别是:useId 设计目标就是让 React 在 SSR 和 hydration 场景里能保持一致,而随机字符串做不到这一点。
Q2:为什么不能拿它做 key?
因为列表 key 的核心目的是描述“这条数据是谁”,而不是“这次渲染生成了什么 ID”。它应该和业务数据稳定绑定。
Q3:React 18 为什么新增它?
因为并发渲染和 SSR/hydration 场景更常见,React 需要一个官方方案来解决组件内 DOM 关联 ID 的一致性问题。
常见追问
1)每次 render 它会变吗?
不会随普通重渲染随机变化,它的目的就是稳定。
2)它是不是全局唯一?
在 React 树和使用语境里可认为足够唯一,但它的目标不是做跨系统全局唯一主键。
易错点/坑
- 用
useId生成列表key。 - 用它充当数据库主键。
- 不知道它是 React 18 新增,答不出它出现的背景。
速记要点(可背诵)
useId:React 18 新增,用于 SSR/CSR 一致的稳定 DOM ID。- 典型用途:
label/input、aria-*关联。 - 不用于列表 key,不用于业务主键。