Skip to content
Advertisement

React JS Animated accordion – built using details and summary

I’m currently building a custom accordion in React using <details /> and <summary /> Here’s what I have so far – codesandbox

As you can see in the codesandbox, a weird problem is happening. Every time I click on one of the accordions, only the last item’s content shows up. I can’t figure out what’s causing the weird issue.

A snippet of my handle click function, for a full code please refer to the sandbox link above:

  const handleClick = (e) => {
    e.preventDefault();

    const accordion = summaryRef.current.parentNode;
    const content = contentRef.current;

    if (accordion.hasAttribute("open")) {
      content.style.removeProperty("max-height");
      content.classList.add("closed");
      setTimeout(() => {
        accordion.removeAttribute("open");
      }, 400);
      return;
    }
    // If the <details> element is closed, add the [open] attribute (so the content will render), and animate in
    accordion.setAttribute("open", "");
    // Get proper max-height for element for better animation
    if (!content.getAttribute("data-height")) {
      content.style.maxHeight = "none";
      content.setAttribute(
        "data-height",
        `${content.getBoundingClientRect().height}px`
      );
      content.style.removeProperty("max-height");
    }
    // Wait for the browser to apply [open] to <details>, then animate
    setTimeout(() => {
      content.classList.remove("closed");
      content.style.maxHeight = content.getAttribute("data-height");
    }, 0);
  };

Any help/suggestions would be greatly appreciated!!

Advertisement

Answer

This is happening because you re-reference summaryRef and contentRef in a for loop. Because that the actual value of refs will be last item. I advice to make items as a separate components and keep refs under them.

Advertisement