Первым шагом в создании компонента accordion является определение "частей" пользовательского интерфейса, чтобы понять, нужно ли нам создавать только один компонент или несколько.

Глядя на конечный результат, мы замечаем, что часть заголовок + содержание повторяется, так что это отличный кандидат для компонента.

Таким образом, давайте создадим AccordionHeading компонент для заголовка + сворачиваемый контент и еще один Accordion компонент как оболочка для списка.

Заголовок "Аккордеон”

Каждый заголовок получит title и content и будет отображать их, позволяя пользователю щелкнуть по заголовку, чтобы развернуть / свернуть содержимое.

Содержимое может быть передано как пропс, точно так же, как title, но я решил выдать это за children для более удобного компонентного использования:

<AccordionHeader title="What is Github and how does it work?">
	GitHub is the home for all developers—a platform where you can share code ...
</AccordionHeader

Вот окончательный код компонента:

const AccordionHeader = ({ title, children }) => {
  const [isOpen, setOpen] = useState(false);
  return (
    <section>
      <h3 onClick={() => setOpen(!isOpen)}>{title}</h3>
      {isOpen && <p>{children}</p>}
    </section>
  );
};

Обертка для аккордеона

Далее, давайте создадим компонент-оболочку, который будет отображать список. Он просто возьмет список и будет перебирать его элементы, чтобы отобразить каждый из них в виде AccordionHeader.

const Accordion = ({ items }) => (
  <div>
    {items.map((item) => (
      <AccordionHeader key={item.title} title={item.title}>{item.content}</AccordionHeader>
    ))}
  </div>
);

<aside> 📖

Вы можете ознакомиться с полным рабочим решением в этом разделе. CodeSandbox: https://codesandbox.io/p/sandbox/faq-accordion-y85ys9

</aside>

Дополнительный вопрос: Как раскрывавать только один элемент за раз