You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Accordion组件WAI-ARIA属性唯一ID的推荐实现方式咨询

React Accordion组件的唯一ID实现方案推荐

我正在尝试创建带有WAI-ARIA属性的Accordion组件,但部分元素需要引用唯一ID。其中Accordion的内容(accordion__content)必须拥有唯一ID,供按钮的aria-controls属性引用。由于该组件可能在页面中多次使用,固定ID(比如'any-id')显然不可行。

用户提供的组件代码:

type AccordionProps = {
  children: ReactNode;
  label: string;
};

export const Accordion = ({ label, children }: AccordionProps) => {
  const { isContentShowing, setIsContentShowing } = useAccordion();

  return (
    <div className="accordion" aria-label={`${label} Accordion`} data-testid="accordion">
      <button
        className="accordion__button"
        onClick={setIsContentShowing}
        aria-expanded={isContentShowing}
        aria-controls="UNIQUE-ID"
      >
        <span className="accordion__text">{label}</span>
        <AccordionArrowIcon isContentShowing={isContentShowing} />
      </button>
      {isContentShowing && (
        <div className="accordion__content" id="UNIQUE-ID" aria-hidden={!isContentShowing}>
          {children}
        </div>
      )}
    </div>
  );
};

目前有两种思路:生成随机ID并分配给对应属性,或是将ID作为props传入。请问是否有推荐的实现方式?


推荐实现方式:自动生成ID + 可选自定义ID

两种方案各有价值,结合使用能兼顾易用性和灵活性:

1. 优先用React内置的useId()自动生成ID(默认逻辑)

React 18+提供的useId()钩子是专门为这种场景设计的,它能生成稳定且唯一的ID,同时避免服务端渲染(SSR)时前后端ID不匹配导致的hydration报错,比自己用Math.random()生成随机ID更可靠。

2. 保留自定义ID传入的选项(特殊场景适配)

如果需要手动控制ID(比如自动化测试定位、锚点跳转、和其他组件联动),可以把ID设为可选props,优先使用传入的ID,没有则用自动生成的。

修改后的组件代码示例:

import { useId } from 'react';

type AccordionProps = {
  children: ReactNode;
  label: string;
  id?: string; // 可选自定义ID
};

export const Accordion = ({ label, children, id: propId }: AccordionProps) => {
  const { isContentShowing, setIsContentShowing } = useAccordion();
  const generatedId = useId();
  // 优先使用传入的ID,无传入则用自动生成的
  const accordionId = propId || `accordion-content-${generatedId}`;

  return (
    <div className="accordion" aria-label={`${label} Accordion`} data-testid="accordion">
      <button
        className="accordion__button"
        onClick={setIsContentShowing}
        aria-expanded={isContentShowing}
        aria-controls={accordionId}
      >
        <span className="accordion__text">{label}</span>
        <AccordionArrowIcon isContentShowing={isContentShowing} />
      </button>
      {isContentShowing && (
        <div className="accordion__content" id={accordionId} aria-hidden={!isContentShowing}>
          {children}
        </div>
      )}
    </div>
  );
};

方案优势说明

  • 自动生成ID:降低组件使用成本,不用每次都手动传ID,避免重复ID风险。
  • 支持自定义ID:满足特殊场景需求,比如测试时可以固定ID方便定位元素。
  • SSR友好:useId()生成的ID在前后端渲染时保持一致,不会出现hydration问题。

内容的提问来源于stack exchange,提问作者Victor Santizo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 21:32:52