Closing Accordions Automatically

Hello everyone!

I'm currently working on a NextJS project and facing an issue with my dynamic accordion component. I'm using typescript, and the problem lies in only one accordion being able to open at a time. How can I ensure that only the specific one clicked on is toggled?

Currently, if there is already an active accordion, it automatically closes the previous one when attempting to open a new one. I want users to be able to open as many accordions as they wish without forcing the others to close.

Below is the snippet of my code:

import React, { useState } from 'react'
import { FaChevronDown, FaChevronUp } from 'react-icons/fa';

const faqList = () => {
  const faqArr = [
    // FAQs data
  ];
  
  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='accordionWrapper'>
              <div className={accordion === id ? 'open' : ''}>
                <div className='accordionHead'>
                  <h6>{FAQ.faqQuestion}</h6>
                    { accordion === id ? (
                      <FaChevronUp />
                    ) : (
                      <FaChevronDown />
                    ) }
                </div>
              </div>
              <div className={accordion === id ? 'content open' : 'content'}>
                <p>{FAQ.answer}</p>
              </div>
            </div>)
        }
      </div>
    </>
  )
}

export default faqList

Answer №1

To ensure your accordion functions properly, it is important that the state is set as an array containing the indexes of active items. You can achieve this by creating a Item component to manage this functionality.

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>
    );
};

You can then utilize this component within the 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>
        </>
    );
};

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Unable to direct to the main page in index.js of the next.js application

I have been working on a next.js application and encountered an issue with a component I created called <ButtonGroup>. I added a button with the code <Button href="index">Home</Button> to allow users to navigate back to the home ...

The inclusion of HttpClient is causing issues with the functionality of my component

Currently, I am facing an issue with my Angular service called ConnexionService. The problem arises when I try to incorporate CSV files into this service using HttpClient. Strangely, the component associated with this service fails to display once HttpClie ...

What methods can I use to analyze the integrity of the data's structure?

Currently working on an API using NestJS and typeorm. I am in need of a way to verify the format of the data being returned to clients who make requests to it. For instance, when accessing the /players route, I expect the data to have a specific structure ...

Is there an alternative method to incorporate the 'environment.ts' file into a JSON file?

In my Angular application, I need to import assets based on the env configuration. I am attempting to extract the patch information from environment.ts and save it into my assets as a json file. However, I am unsure of the proper method to accomplish this. ...

Next.js React Server Components Problem - "ReactServerComponentsIssue"

Currently grappling with an issue while implementing React Server Components in my Next.js project. The specific error message I'm facing is as follows: Failed to compile ./src\app\components\projects\slider.js ReactServerComponent ...

Using `this` within an object declaration

I am encountering an issue with the following code snippet: const myObj = { reply(text: string, options?: Bot.SendMessageOptions) { return bot.sendMessage(msg.chat.id, text, { reply_to_message_id: msg.message_id, ...options }) ...

TypeScript: When using an API, it consistently returns an empty object with the type { [key: string]: any }

Every time I try to fetch data from the API, it always comes back empty. See example code snippet below: interface DataStore { [key: string]: any, } static GetData = async (req: Request, res: Response): Promise<Response> => { let obj: Dat ...

Can you explain how this promise functions within the context of the mutation observer, even without an argument?

Recently, I came across a mutation observer in some TypeScript code that has left me puzzled. This particular implementation of a promise within the mutation observer seems unconventional to me: const observer = new MutationObserver((mutations: MutationR ...

How can Next-auth handle redirection for 401 errors?

Currently, I am utilizing Next-auth in combination with rtk query. My goal is to configure the application so that whenever a request results in a 401 unauthorized error, the page will automatically redirect to the login page. How can this be achieved? I ...

Discover the seamless transformation of a class definition into a Vue 3 component definition utilizing the dazzling 'tc39' decorators

The proposed API in the tc39/proposal-decorators repository is significantly different from the previous decorators API. Although TypeScript 5 doesn't fully support the new API yet, it's only a matter of time before the old API becomes deprecated ...

Dynamic Session ID Generation in Next.js integration with Express.js Server

I am using Next.js v14 for my frontend and Express.js for the backend. To protect certain routes in Next.js, I have implemented an authentication guard using middleware.ts export default async function middleware(request: Request) { const loginStatus = a ...

What steps should I take to set up my React project in order to eliminate .html extensions from the html files within the public

Currently, I am tackling a project that involves integrating a React app with a static website. Simply converting the HTML to JSX is not feasible because the website utilizes custom CSS that React cannot easily render without significant refactoring. I ha ...

Guide on successfully importing a pretrained model in Angular using TensorFlow.js

I need help with uploading a pretrained Keras model to my existing tensorflow.js model and then making simple predictions by passing tensors in the correct format. The model is stored locally within the project, in the assets folder. export class MotionAn ...

By default, showcase the value of the first item in the list selected in a mat-selection-list on a separate component

In my project, I have two essential components: 1)list (which displays a list of customers) 2)detail (which shows the details of a selected customer) These components are designed to be reusable and are being utilized within another component called cus ...

Attempt to re-establish connection to server callback in Angular 2 upon encountering failure

tag, I have created an API parent class where all the necessary methods are implemented for server communication. The ApiService class is injected with Http and MdSnackBar services to handle HTTP requests and display snack bar messages. The get() method ...

A versatile method for transforming enums into arrays that can handle null values

Looking for a simpler way to create a TypeScript function that converts an enum to an array, including support for null values. Here's an example of what I'm trying to achieve: enum Color { RED = "Red", GREEN = "Green&qu ...

Increase the timestamp in Typescript by one hour

Is there a way to extend a timestamp by 1 hour? For instance, 1574620200000 (Including Microseconds) This is my date in timestamp format. How can I add a value to the timestamp to increase the time by an additional hour? ...

Caching with Next.js even when no-cache header is present

I'm currently working on a project using Next.js version 13.4.12. It communicates with our Express API hosted on a separate server. The API returns JSON data with a no-cache header. X-Powered-By: Express Cache-Control: no-cache, no-store, must-revali ...

Is There a Comparable Feature to *ngIf in DevExtreme?

Currently, I am diving into the world of webapp development using DevExtreme. As a novice in coding, this is my first time exploring the functionalities of DevExtreme. Essentially, I am seeking guidance on how to display certain elements based on specific ...

Is there a missing .fillGeometry in the Figma plugin VectorNode?

The documentation for VectorNode mentions a property called fillGeometry. Contrary to this, TypeScript indicates that "property 'fillGeometry' does not exist on type 'VectorNode'". I seem to be missing something here. Can someone prov ...