skip to Main Content

I would like to make an accordion with react but do that when I click on a title it’s all the others that are displayed instead of just one.
I would like to make an accordion with react but do that when I click on a title it’s all the others that are displayed instead of just one.

import { useState } from "react"
import "./sidebar.css"
import sublinks from '../../data'
const Sidebar = () => {
  const [showInfo, setShowInfo] = useState(false)
  
  console.log(showInfo)
  return (
    <div className="sidebar show">
      <div className="sidebar__container">
        <button className="close-btn">x</button>
        <div className="sidebar__container__w">
          {sublinks.map((item, index) =>{
            const {links, page}= item
            return (
              <div className="sidebar__menu__wrapper" key={index}>
                <button
                  className="sidebar__menu"
                  onClick={() => setShowInfo(!showInfo)}
                >
                  {page}
                </button>

                {showInfo && (
                  <div className=" side__Links" key={index} >
                    {links.map((link,index) =>{
                      const {label,url} = link
                      return (
                        <a key={index} href={url} className="side__Link">
                          {label}
                        </a>
                      )
                    })}
                  </div>
                ) }
              </div>
            )
          })

          }
          
        </div>
      </div>
    </div>
  )
}
export default Sidebar

2

Answers


  1. You have a boolean state variable which though affects all links.
    So what you need to have at your state is an array state variable which stores the opened accordions,

    const [shownLinks, setShownLinks] = useState([])
    

    for the button click

    onClick={() => {
      if (shownLinks.includes(page) {
        setShownLinks(shownLinks.filter(link => link !== page)
      } else {
       setShownLinks([...shownLinks, page])
      }
    }
    

    and finally for the show/hide boolean part

    {shownLinks.includes(page) && (
    
    Login or Signup to reply.
  2. That is because you only have "one" condition and all the sections use it.
    You can use a js object instead of a single boolean.

    Try this:

    import "./sidebar.css"
    import sublinks from '../../data'
    const Sidebar = () => {
      const [expandedSections, setExpandedSections] = useState({});
    
      const toggleSection = index => {
        setExpandedSections(prev => {
          const newState = {...prev}
          newState[index] = !newState[index];
          return prev;
        })
      }
      
      return (
        <div className="sidebar show">
          <div className="sidebar__container">
            <button className="close-btn">x</button>
            <div className="sidebar__container__w">
              {sublinks.map((item, index) =>{
                const {links, page}= item
                return (
                  <div className="sidebar__menu__wrapper" key={index}>
                    <button
                      className="sidebar__menu"
                      onClick={() => toggleSection(index)}
                    >
                      {page}
                    </button>
    
                    {expandedSections[index] && (
                      <div className=" side__Links" key={index} >
                        {links.map((link,index) =>{
                          const {label,url} = link
                          return (
                            <a key={index} href={url} className="side__Link">
                              {label}
                            </a>
                          )
                        })}
                      </div>
                    ) }
                  </div>
                )
              })
    
              }
              
            </div>
          </div>
        </div>
      )
    }
    export default Sidebar
    

    Or if you want to open one section at a time, do this:

    import { useState } from "react"
    import "./sidebar.css"
    import sublinks from '../../data'
    const Sidebar = () => {
      const [activeIndex, setActiveIndex] = useState(null);
    
      const toggleSection = index => {
        setActiveIndex(activeIndex === index ? null : index)
      }
      
      return (
        <div className="sidebar show">
          <div className="sidebar__container">
            <button className="close-btn">x</button>
            <div className="sidebar__container__w">
              {sublinks.map((item, index) =>{
                const {links, page}= item
                return (
                  <div className="sidebar__menu__wrapper" key={index}>
                    <button
                      className="sidebar__menu"
                      onClick={() => toggleSection(index)}
                    >
                      {page}
                    </button>
    
                    {activeIndex === index && (
                      <div className=" side__Links" key={index} >
                        {links.map((link,index) =>{
                          const {label,url} = link
                          return (
                            <a key={index} href={url} className="side__Link">
                              {label}
                            </a>
                          )
                        })}
                      </div>
                    ) }
                  </div>
                )
              })
    
              }
              
            </div>
          </div>
        </div>
      )
    }
    export default Sidebar
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search