跳到主要内容

标识与调试 Hooks

如何生成无障碍关联所需的 ID?​

  • useId: 为组件调用位置生成 ID,适合 label、描述文本与输入的 aria 关系,同一组件可在该 ID 后添加后缀形成一组关联;
  • 无条件调用: 在组件或自定义 Hook 顶层调用,不能为了只在某分支显示输入而条件调用;
  • 非数据身份: 不用 useId 生成列表 key 或 use 的资源缓存 key,这些身份必须来自数据,不能依赖尚未挂载时可能变化的组件 ID;
import { useId } from "react";

function PasswordField() {
const id = useId();
return (
<>
<label htmlFor={id}>密码</label>
<input id={id} type="password" aria-describedby={id + "-hint"} />
<p id={id + "-hint"}>请使用足够长的密码。</p>
</>
);
}

服务端渲染与多个 root 如何保持 ID 一致?​

  • 树一致: useId 支持服务端与客户端相同树结构下的匹配,不能补救两端渲染结构不同;
  • 根前缀: 多个独立 root 可用 identifierPrefix 避免冲突,服务端与 hydrateRoot 必须使用一致前缀;
  • 调用限制: 当前不能在 async Server Components 中调用 useId,需要在适当组件边界生成标识;

如何让自定义 Hook 在 DevTools 中更易读?​

  • useDebugValue: 给 React DevTools 中的自定义 Hook 添加可读标签,不会把调试值渲染到页面;
  • 按需使用: 复杂、共享的 Hook 适合标注,不必给每个简单 Hook 添加额外标签;
  • 延迟格式化: 第二参数是 formatter,只在检查 Hook 时格式化,避免每次渲染进行昂贵调试计算;
import { useDebugValue } from "react";

function useNamedDebugValue(value) {
useDebugValue(value, (current) => `当前值:${current}`);
return value;
}

ID 与调试值能否承担业务状态?​

  • 明确用途: useId 解决可访问性关联,useDebugValue 解决工具展示,两者都不替代数据库 ID 或可更新的业务 state;