标准答案

  1. useId 会生成适合当前 React 树的稳定 id,服务端渲染和客户端 hydration 时能保持一致。
  2. 它适合把 label 和 input、说明文本和控件、错误提示和字段用 aria 属性关联起来。
  3. 它不适合用作列表 key。列表 key 应来自数据身份,而不是组件内部生成的 id。
  4. 多个组件实例调用 useId 时,React 会保证同一棵树内的 id 不冲突。
  5. 如果 id 需要和业务数据、URL、后端记录对应,应使用业务 id,而不是 useId。

题目解析

这道题要同时讲 SSR 和可访问性。随机 id 在服务端和客户端可能不同,会造成 hydration 警告。

useId 的价值在组件库里很明显:组件需要默认生成 label/input 关联 id,同时允许外部传入 id 覆盖。

不要把 useId 当成通用唯一 id 工具。它是 React 渲染树里的稳定 id,不是数据库 id 或列表 key。

代码示例

下面的字段组件用 useId 建立 label、input 和错误提示之间的关联。

TSX
function TextField({ label, error }: { label: string; error?: string }) {
  const id = useId()
  const errorId = `${id}-error`

  return (
    <div>
      <label htmlFor={id}>{label}</label>
      <input
        id={id}
        aria-invalid={Boolean(error)}
        aria-describedby={error ? errorId : undefined}
      />
      {error ? <p id={errorId}>{error}</p> : null}
    </div>
  )
}

常见误区

  • 用 Math.random 生成表单 id,SSR 时服务端和客户端 id 不一致。
  • 把 useId 生成的值当列表 key 使用。
  • 只渲染视觉上的 label,没有用 htmlFor、aria-describedby 建立可访问性关联。

作者信息