英文:
WAI-ARIA attribute needs a unique id, however this react component might be created multiple times
问题
我试图创建一个具有WAI-ARIA属性的手风琴组件,然而,一些元素需要引用一个唯一的id。在这种情况下,手风琴的内容(accordion__content
)必须具有一个唯一的id,该id由按钮的属性aria-controls
引用。
由于该组件可能在页面的不同位置多次使用,使用'any-id'作为id将不起作用。
一种选择是生成一个随机id,然后将该id分配给属性,或者我们还可以将id作为prop传入。是否有推荐的方法来执行这个操作?
英文:
I'm trying to create an Accordion component with WAI-ARIA attributes, however, some elements are required to reference a unique id. In this case, the Accordion's content (accordion__content
) has to have a unique id that is referenced by the button's attribute aria-controls
.
Since the component might be used multiple times in different places within the page, using 'any-id' as an id would not work.
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>
);
};
One option would be to generate a random id and just assign that id to the attributes, or we could also take the id as a prop. Is there any recommended way for doing this?
答案1
得分: 2
以下是翻译好的部分:
当我在过去遇到这样的问题时,我会为组件生成一个 UUID。这将使你的代码如下所示:
import React from "react";
// 这是我会使用的库,但随意根据你的需求创建 ID
import { uuid } from 'uuidv4';
type AccordionProps = {
children: ReactNode;
label: string;
};
export const Accordion = ({ label, children }: AccordionProps) => {
const { isContentShowing, setIsContentShowing } = useAccordion();
// 请注意,ID 将在每次重新渲染时重新生成,但在内部仍然保持一致
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
并没有起作用。从逻辑上讲,它永远不会为 true,因为当内容不显示时,该元素不存在。
英文:
When I've had problems like this in the past, I've generated a uuid for the component. That would make your code like this:
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>
);
Also, your aria-hidden
isn't doing anything. There's logically no point where it would be true, since the element doesn't exist when the content isn't showing.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论