reactjs WAI-ARIA属性需要唯一的ID,但此React组件可能会创建多次

xt0899hw  于 2023-03-12  发布在  React
关注(0)|答案(1)|浏览(112)

我试图创建一个具有WAI-ARIA属性的Accordion组件,但是,某些元素需要引用唯一的id。在本例中,Accordion的内容(accordion__content)必须具有由按钮的属性aria-controls引用的唯一id。
由于该组件可能在页面中的不同位置多次使用,因此使用“any-id”作为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分配给属性,或者我们也可以将id作为一个 prop 。

0vvn1miw

0vvn1miw1#

当我在过去遇到类似的问题时,我为组件生成了一个uuid,这样你的代码就像这样:

import React from "react";
// This is the library I'd use, but feel free to make up the ID however you want
import { uuid } from 'uuidv4';

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

export const Accordion = ({ label, children }: AccordionProps) => {
  const { isContentShowing, setIsContentShowing } = useAccordion();
  // Note that the ID will be regenerated on every re-render, but will still stay internally consistent
  const id = uuid();

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

而且,aria-hidden没有做任何事情,逻辑上没有为真的点,因为当内容没有显示时,元素不存在。

相关问题