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

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

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 &quot;react&quot;;
// This is the library I&#39;d use, but feel free to make up the ID however you want
import { uuid } from &#39;uuidv4&#39;;

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

export const Accordion = ({ label, children }: AccordionProps) =&gt; {
  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 (
    &lt;div className=&quot;accordion&quot; aria-label={`${label} Accordion`} data-testid=&quot;accordion&quot;&gt;
      &lt;button
        className=&quot;accordion__button&quot;
        onClick={setIsContentShowing}
        aria-expanded={isContentShowing}
        aria-controls={id}
      &gt;
        &lt;span className=&quot;accordion__text&quot;&gt;{label}&lt;/span&gt;
        &lt;AccordionArrowIcon isContentShowing={isContentShowing} /&gt;
      &lt;/button&gt;
      {isContentShowing &amp;&amp; (
        &lt;div className=&quot;accordion__content&quot; id={id} aria-hidden={!isContentShowing}&gt;
          {children}
        &lt;/div&gt;
      )}
    &lt;/div&gt;
  );

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:

确定