guys.
I'm building a NextJS project, and have a component that dynamically creates accordions on a page. I'm using typescript and having an issue with only one accordion being able to open at a time. How do I make sure that only the specific one clicked is being toggled?
Because currently, if there is an already active accordion, it will automatically close the previous one if I try to open another. I need it to allow people to open as many as they want, and not force the others to close when another is clicked.
Here is my code:
import React, { useState } from 'react'
import { FaChevronDown, FaChevronUp } from 'react-icons/fa';
const faqList = () => {
const faqArr = [
{ id: 1, faqQuestion: 'Lorem Ipsum Dolor Sit Amet?', answer: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam eu turpis molestie, dictum est a, mattis tellus. Sed dignissim, metus nec fringilla accumsan, risus sem sollicitudin lacus, ut interdum tellus elit sed risus. Maecenas eget condimentum velit, sit amet feugiat lectus. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos.' },
{ id: 2, faqQuestion: 'Lorem Ipsum Dolor Sit Amet?', answer: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam eu turpis molestie, dictum est a, mattis tellus. Sed dignissim, metus nec fringilla accumsan, risus sem sollicitudin lacus, ut interdum tellus elit sed risus. Maecenas eget condimentum velit, sit amet feugiat lectus. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos.' },
{ id: 3, faqQuestion: 'Lorem Ipsum Dolor Sit Amet?', answer: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam eu turpis molestie, dictum est a, mattis tellus. Sed dignissim, metus nec fringilla accumsan, risus sem sollicitudin lacus, ut interdum tellus elit sed risus. Maecenas eget condimentum velit, sit amet feugiat lectus. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos.' },
{ id: 4, faqQuestion: 'Lorem Ipsum Dolor Sit Amet?', answer: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam eu turpis molestie, dictum est a, mattis tellus. Sed dignissim, metus nec fringilla accumsan, risus sem sollicitudin lacus, ut interdum tellus elit sed risus. Maecenas eget condimentum velit, sit amet feugiat lectus. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos.' },
{ id: 5, faqQuestion: 'Lorem Ipsum Dolor Sit Amet?', answer: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam eu turpis molestie, dictum est a, mattis tellus. Sed dignissim, metus nec fringilla accumsan, risus sem sollicitudin lacus, ut interdum tellus elit sed risus. Maecenas eget condimentum velit, sit amet feugiat lectus. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos.' },
{ id: 6, faqQuestion: 'Lorem Ipsum Dolor Sit Amet?', answer: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam eu turpis molestie, dictum est a, mattis tellus. Sed dignissim, metus nec fringilla accumsan, risus sem sollicitudin lacus, ut interdum tellus elit sed risus. Maecenas eget condimentum velit, sit amet feugiat lectus. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos.' },
];
const [accordion, setActiveAccordion] = useState(-1);
let toggleAccordion = (id: number) => {
if (id === accordion) {
setActiveAccordion(-1);
return;
}
setActiveAccordion(id);
}
return (
<>
<div className='grid grid-cols-1 xl:grid-cols-2'>
{
faqArr.map((FAQ, id) =>
<div key={id} onClick={() => toggleAccordion(id)} className='gap-12 mt-2 mb-2 cursor-pointer ease-in'>
<div className={accordion === id ? 'block' : ''}>
<div className='flex justify-between pt-4 pr-6 pb-4 pl-6 border-2 m-2 rounded-xl text-black dark:text-white bg-white dark:bg-black relative z-auto dark:border-white'>
<h6 className="self-center font-bold">{FAQ.faqQuestion}</h6>
{ accordion === id ? (
<FaChevronUp className='text-k-dGray dark:text-k-lGray self-center' />
) : (
<FaChevronDown className='text-k-dGray dark:text-k-lGray self-center' />
) }
</div>
</div>
<div className={accordion === id ? 'block ease-in' : 'hidden ease-in'}>
<p className='flex pt-8 pr-6 pb-4 pl-6 border-l-2 border-r-2 border-b-2 m-2 -mt-6 rounded-xl text-k-dGray dark:text-k-lGray z-0 rounded-tl-none rounded-tr-none border-[666]'>{FAQ.answer}</p>
</div>
</div>)
}
</div>
</>
)
}
export default faqList
CodePudding user response:
Your accordion
state should be a array of active item index. So you can create a Item
component to handle
const Item = ({ isOpen, FAQ, onClick }) => {
return (
<div
onClick={onClick}
className="mt-2 mb-2 cursor-pointer gap-12 ease-in"
>
<div className={isOpen ? 'block' : ''}>
<div className="relative z-auto m-2 flex justify-between rounded-xl border-2 bg-white pt-4 pr-6 pb-4 pl-6 text-black dark:border-white dark:bg-black dark:text-white">
<h6 className="self-center font-bold">{FAQ.faqQuestion}</h6>
{isOpen ? (
<FaChevronUp className="text-k-dGray dark:text-k-lGray self-center" />
) : (
<FaChevronDown className="text-k-dGray dark:text-k-lGray self-center" />
)}
</div>
</div>
<div className={isOpen ? 'block ease-in' : 'hidden ease-in'}>
<p className="text-k-dGray dark:text-k-lGray border-[666] z-0 m-2 -mt-6 flex rounded-xl rounded-tl-none rounded-tr-none border-l-2 border-r-2 border-b-2 pt-8 pr-6 pb-4 pl-6">
{FAQ.answer}
</p>
</div>
</div>
);
};
and you can use it in faqList
const faqList = () => {
const [accordion, setActiveAccordion] = useState([]);
const toggleAccordion = (id: number) => {
const newArray = accordion.includes(id) ? accordion.filter(i => i !== id) : [...accordion, id]
setActiveAccordion(newArray)
};
return (
<>
<div className="grid grid-cols-1 xl:grid-cols-2">
{faqArr.map((FAQ, id) => (
<Item
key={id}
FAQ={FAQ}
isOpen={accordion.includes(id)}
onClick={() => toggleAccordion(id)}
/>
))}
</div>
</>
);
};