当前位置: 首页 > article >正文

react中hooks之useId用法总结以及与useRef用法区别

React useId Hook 使用指南

概述

useId 是 React 18 引入的新 Hook,用于生成唯一的 ID,主要用于可访问性(accessibility)属性。它在服务端和客户端渲染时都能保持一致性。

useId vs useRef

  • useId: 生成稳定的唯一标识符,主要用于 HTML 属性关联
  • useRef: 存储可变值的容器,主要用于保存引用和状态

基本用法

1. useId 基础示例

function FormField() {
  const id = useId();
  return (
    <div>
      <label htmlFor={id}>Name:</label>
      <input id={id} type="text" />
    </div>
  );
}

2. 多个关联 ID

function ComplexForm() {
  const id = useId();
  return (
    <form>
      <div>
        <label htmlFor={`${id}-name`}>Name:</label>
        <input id={`${id}-name`} type="text" />
      </div>
      <div>
        <label htmlFor={`${id}-email`}>Email:</label>
        <input id={`${id}-email`} type="email" />
      </div>
    </form>
  );
}

3. ARIA 属性使用

function Accordion() {
  const id = useId();
  return (
    <div>
      <button 
        aria-controls={`${id}-content`}
        aria-expanded="false"
      >
        Toggle
      </button>
      <div 
        id={`${id}-content`}
        aria-labelledby={`${id}-header`}
      >
        Content
      </div>
    </div>
  );
}

useId vs useRef 对比

1. 用途区别

// useId: 生成稳定的 ID
function AccessibleInput() {
  const id = useId();
  return (
    <div>
      <label htmlFor={id}>Input:</label>
      <input id={id} />
    </div>
  );
}

// useRef: 保存元素引用或可变值
function FocusInput() {
  const inputRef = useRef<HTMLInputElement>(null);
  
  const focus = () => {
    inputRef.current?.focus();
  };

  return (
    <div>
      <input ref={inputRef} />
      <button onClick={focus}>Focus</button>
    </div>
  );
}

2. 生命周期差异

// useId: 组件整个生命周期保持稳定
function StableId() {
  const id = useId();
  // id 在重渲染时保持不变
  return <div id={id}>{id}</div>;
}

// useRef: 可以随时更新值
function Counter() {
  const countRef = useRef(0);
  
  const increment = () => {
    countRef.current += 1;  // 更新值不会触发重渲染
    console.log(countRef.current);
  };

  return <button onClick={increment}>Increment</button>;
}

3. 服务端渲染考虑

// useId: 服务端和客户端保持一致
function ServerComponent() {
  const id = useId();
  // 在 SSR 和客户端渲染中生成相同的 ID
  return <div id={id}>Content</div>;
}

// useRef: 主要用于客户端
function ClientComponent() {
  const elementRef = useRef<HTMLDivElement>(null);
  // ref 在服务端渲染时为 null
  useEffect(() => {
    console.log(elementRef.current);  // 仅在客户端可用
  }, []);

  return <div ref={elementRef}>Content</div>;
}

最佳实践

1. 可访问性组件

function AccessibleDialog() {
  const id = useId();
  return (
    <div>
      <button 
        aria-haspopup="dialog"
        aria-controls={`${id}-dialog`}
      >
        Open Dialog
      </button>
      <div
        role="dialog"
        id={`${id}-dialog`}
        aria-labelledby={`${id}-title`}
        aria-describedby={`${id}-desc`}
      >
        <h2 id={`${id}-title`}>Dialog Title</h2>
        <p id={`${id}-desc`}>Dialog description</p>
      </div>
    </div>
  );
}

2. 表单控件关联

function FormGroup({ label, type = "text" }) {
  const id = useId();
  const errorId = `${id}-error`;
  const descriptionId = `${id}-description`;

  return (
    <div>
      <label htmlFor={id}>{label}</label>
      <input
        id={id}
        type={type}
        aria-describedby={`${descriptionId} ${errorId}`}
      />
      <span id={descriptionId}>Help text</span>
      <span id={errorId} role="alert"></span>
    </div>
  );
}

使用建议

  1. useId 适用场景:

    • HTML 元素 ID 生成
    • ARIA 属性关联
    • 表单标签关联
    • 需要服务端渲染一致性的场景
  2. useRef 适用场景:

    • DOM 元素引用
    • 存储可变值
    • 计时器/订阅的引用
    • 需要在不触发重渲染的情况下更新值
  3. 选择建议:

    • 需要稳定的唯一标识符时使用 useId
    • 需要存储可变引用时使用 useRef
    • 考虑服务端渲染需求
    • 考虑可访问性需求

总结

  1. useId 特点:

    • 生成稳定的唯一标识符
    • 服务端渲染兼容
    • 适合可访问性属性
    • 组件级别的唯一性
  2. useRef 特点:

    • 存储可变值
    • 不触发重渲染
    • 适合 DOM 引用
    • 组件内部状态管理
  3. 使用场景区分:

    • HTML/ARIA 属性关联用 useId
    • DOM 操作和可变值存储用 useRef
    • 考虑渲染一致性需求
    • 考虑值更新特性

http://www.kler.cn/a/514325.html

相关文章:

  • 软件测试入门—用例设计中的场景图和状态迁移图
  • 图解Git——分布式Git《Pro Git》
  • 线性规划:机器学习中的优化利器
  • Node.js 完全教程:从入门到精通
  • 基础jjj
  • 1170 Safari Park (25)
  • LeetCode hot 力扣100 LRU 缓存
  • 升级到MySQL 8.4,MySQL启动报错:io_setup() failed with EAGAIN
  • KubeKey安装K8s和kubesphere
  • ConvBERT:通过基于跨度的动态卷积改进BERT
  • 【Linux入门】2w字详解yum、vim、gcc/g++、gdb、makefile以及进度条小程序
  • 电脑办公技巧之如何在 Word 文档中添加文字或图片水印
  • 使用Sum计算Loss和解决梯度累积(Gradient Accumulation)的Bug
  • C# LINQ(Language Integrated Query)详解
  • docker部署的gitlab迁移
  • 图像点处理
  • 使用 vllm 部署 MiniCPM-o 2.6
  • Logo语言的操作系统
  • PostIn安装教程
  • Windows电脑安装USB Redirector并实现内外网跨网USB共享通信访问
  • Python爬虫学习第一弹 —— 爬虫的基础知识 及 requests基础
  • 深入理解机器学习中的零样本、少样本与微调
  • 金融场景 PB 级大规模日志平台:中信银行信用卡中心从 Elasticsearch 到 Apache Doris 的先进实践
  • uniapp的插件开发发布指南
  • FPGA 开发工作需求明确:关键要点与实践方法
  • 软件方法论--课程笔记(整理中)