D
D
Devero972022-03-21 14:28:02
React
Devero97, 2022-03-21 14:28:02

How to process each button in an array so that one item opens and not all?

I have an accordion. Passing data in an array. When you click on any button, all hints open. How can I pass the correct index to a function and only call it on a specific button?

import { useRef, useState } from "react";

export const Accordion = ({ accordionList }) => {
  const [active, setActive] = useState(false);
  const [height, setHeight] = useState("0px");
  const [rotate, setRotate] = useState("transform duration-700 ease");

  const contentSpace = useRef<HTMLDivElement>(null);

  function toggleAccordion() {
    setActive((prevState) => !prevState);
    setHeight(active ? "0px" : `${contentSpace.current?.scrollHeight || 0}px`);
    setRotate(
      active
        ? "transform duration-700 ease"
        : "transform duration-700 ease rotate-180"
    );
  }

  return (
    <>
      <div className="mx-auto  flex max-w-7xl flex-col px-4 pb-8 sm:px-8 sm:pb-12">
        <div className="rounded-lg border-t bg-white shadow">
          {accordionList.map((item, index) => (
            <div>
              <button
                key={index}
                className="box-border flex w-full  cursor-pointer appearance-none items-center justify-between px-4 py-4 shadow  focus:outline-none sm:px-6"
                onClick={toggleAccordion}
              >
                <p className="text-base font-medium leading-6">{item.title}</p>
                <svg
                  xmlns="http://www.w3.org/2000/svg"
                  className={`${rotate} h-5 w-5 text-black`}
                  fill="none"
                  viewBox="0 0 24 24"
                  stroke="currentColor"
                  stroke-width="2"
                >
                  <path
                    stroke-linecap="round"
                    stroke-linejoin="round"
                    d="M5 15l7-7 7 7"
                  />
                </svg>
              </button>
              <div
                ref={contentSpace}
                style={{ maxHeight: `${height}` }}
                className="transition-max-height overflow-auto overflow-y-hidden   duration-700 ease-in-out "
              >
                <div className="py-3  px-4  sm:px-6">{item.content}</div>
              </div>
            </div>
          ))}
        </div>
      </div>
    </>
  );
};

Answer the question

In order to leave comments, you need to log in

2 answer(s)
A
Alexander Shipin, 2022-03-21
@alexshipin

An example of an accordion solution

I
Ivan Derbenchenko, 2022-03-21
@Mr_FabiozZz

I think a separate Accordion component with its own state and click handler suggests itself here, and the problem is solved

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question