WAI-ARIA属性需要唯一的ID,然而这个React组件可能会被创建多次。

huangapple go评论89阅读模式
英文:

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.

  1. type AccordionProps = {
  2. children: ReactNode;
  3. label: string;
  4. };
  5. export const Accordion = ({ label, children }: AccordionProps) => {
  6. const { isContentShowing, setIsContentShowing } = useAccordion();
  7. return (
  8. <div className="accordion" aria-label={`${label} Accordion`} data-testid="accordion">
  9. <button
  10. className="accordion__button"
  11. onClick={setIsContentShowing}
  12. aria-expanded={isContentShowing}
  13. aria-controls="UNIQUE-ID"
  14. >
  15. <span className="accordion__text">{label}</span>
  16. <AccordionArrowIcon isContentShowing={isContentShowing} />
  17. </button>
  18. {isContentShowing && (
  19. <div className="accordion__content" id="UNIQUE-ID" aria-hidden={!isContentShowing}>
  20. {children}
  21. </div>
  22. )}
  23. </div>
  24. );
  25. };

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。这将使你的代码如下所示:

  1. import React from "react";
  2. // 这是我会使用的库,但随意根据你的需求创建 ID
  3. import { uuid } from 'uuidv4';
  4. type AccordionProps = {
  5. children: ReactNode;
  6. label: string;
  7. };
  8. export const Accordion = ({ label, children }: AccordionProps) => {
  9. const { isContentShowing, setIsContentShowing } = useAccordion();
  10. // 请注意,ID 将在每次重新渲染时重新生成,但在内部仍然保持一致
  11. const id = uuid();
  12. return (
  13. <div className="accordion" aria-label={`${label} Accordion`} data-testid="accordion">
  14. <button
  15. className="accordion__button"
  16. onClick={setIsContentShowing}
  17. aria-expanded={isContentShowing}
  18. aria-controls={id}
  19. >
  20. <span className="accordion__text">{label}</span>
  21. <AccordionArrowIcon isContentShowing={isContentShowing} />
  22. </button>
  23. {isContentShowing && (
  24. <div className="accordion__content" id={id} aria-hidden={!isContentShowing}>
  25. {children}
  26. </div>
  27. )}
  28. </div>
  29. );

另外,你的 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:

  1. import React from &quot;react&quot;;
  2. // This is the library I&#39;d use, but feel free to make up the ID however you want
  3. import { uuid } from &#39;uuidv4&#39;;
  4. type AccordionProps = {
  5. children: ReactNode;
  6. label: string;
  7. };
  8. export const Accordion = ({ label, children }: AccordionProps) =&gt; {
  9. const { isContentShowing, setIsContentShowing } = useAccordion();
  10. // Note that the ID will be regenerated on every re-render, but will still stay internally consistent
  11. const id = uuid();
  12. return (
  13. &lt;div className=&quot;accordion&quot; aria-label={`${label} Accordion`} data-testid=&quot;accordion&quot;&gt;
  14. &lt;button
  15. className=&quot;accordion__button&quot;
  16. onClick={setIsContentShowing}
  17. aria-expanded={isContentShowing}
  18. aria-controls={id}
  19. &gt;
  20. &lt;span className=&quot;accordion__text&quot;&gt;{label}&lt;/span&gt;
  21. &lt;AccordionArrowIcon isContentShowing={isContentShowing} /&gt;
  22. &lt;/button&gt;
  23. {isContentShowing &amp;&amp; (
  24. &lt;div className=&quot;accordion__content&quot; id={id} aria-hidden={!isContentShowing}&gt;
  25. {children}
  26. &lt;/div&gt;
  27. )}
  28. &lt;/div&gt;
  29. );

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.

huangapple
  • 本文由 发表于 2023年3月3日 17:44:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/75625446.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定