我正在尝试创建一个带有 WAI-ARIA 属性的 Accordion 组件,但是,一些元素需要引用一个唯一的 id。在这种情况下,手风琴的内容 (
accordion__content
) 必须有一个唯一的 id,由按钮的属性 aria-controls
. 引用
由于该组件可能会在页面中的不同位置多次使用,因此使用“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。有什么推荐的方法吗?
当我过去遇到这样的问题时,我已经为组件生成了一个 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
没有做任何事情。逻辑上没有任何意义,因为当内容不显示时元素不存在。