# Accordion App With React

Let's get started.

As always, I first of all design my projects in Figma before I move to development. This way, I do not get confused. I know exactly how to structure the UI as that thinking has already been done and it's in front of me.

Here is what we are going to build.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1707881507272/aa284577-9d24-4815-8de8-d248114b9c5e.png align="center")

If you look at the screenshot of the finished product above, you will see that we have the **header** and the **accordions**. In the accordion components, we have the **topic**, the **question** underneath it and the **answer** (what will be shown when the accordion is expanded).

Every one of these pieces is a separate component. I then returned the parent component (`accordion`) in the `App.js` to render the app.

I started by creating a file `Accordion.jsx` in my `src` directory. This is the file that has all the code for the project.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1707881012091/5e151e28-efcf-4639-9068-352ad2995205.png align="center")

So let's start with each component in the UI.

```javascript
function Accordion() {
    return (
        <div></div>
    )
}
```

For now, we are simply returning an empty div element.

### The `AccordionItem` component.

```javascript
function AccordionItem() {
    return (
        <div className="container">
            <AccordionQuestion/>
            <AccordionAnswer/>
        </div>
    )
}
```

Now let's create the two components we are returning here.

### The `AccordionQuestion` component

```javascript
function AccordionQuestion() {
    return (
        <div className="header">
            <h2>Lorem ipsum dolor sit amet.</h2>
            <div className="question">
                <p>Nam itaque cumque et consectetur magni</p>
                <span>+</span>
            </div>
        </div>
    )
}
```

### The `AccordionAnswer` component

```javascript
function AccordionAnswer() {
    return (
        <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. 
        Doloribus soluta molestias accusantium ut eveniet architecto 
        vero repellendus. Officiis, cupiditate necessitatibus.</p>
    )
}
```

It is always clean and neat for you to write your data in a separate file like JSON or even just a simple object and import it into your app. We have been typing the accordion content manually but that is not the optimal way to do it if we are going to have multiple components.

Let's create a utilities file and write our data in it instead.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1707966840407/7128ad7d-55c8-42fe-8c49-5d73e6c671ab.png align="center")

We write the following object in the file.

```javascript
export const accordionData = [
    {
        subject: 'Lorem ipsum dolor sit amet.',
        question: 'Nam itaque cumque et consectetur magni?',
        answer: `Lorem ipsum dolor sit amet, consectetur adipisicing elit. 
        Nobis perspiciatis recusandae placeat qui, accusamus molestias 
        voluptates cupiditate culpa quo? Magnam atque vero nemo 
        molestiae tenetur. Placeat vel quas quisquam amet doloremque 
        perferendis numquam ut. Hic aut qui alias molestiae at. 
        Aspernatur quam doloremque dolores blanditiis itaque veniam 
        perferendis voluptate repellendus.`
    },

    {
        subject: 'Lorem ipsum dolor sit amet.',
        question: 'Nam itaque cumque et consectetur magni?',
        answer: `Lorem ipsum dolor sit amet, consectetur adipisicing elit. 
        Nobis perspiciatis recusandae placeat qui, accusamus molestias 
        voluptates cupiditate culpa quo? Magnam atque vero nemo 
        molestiae tenetur. Placeat vel quas quisquam amet doloremque 
        perferendis numquam ut. Hic aut qui alias molestiae at. 
        Aspernatur quam doloremque dolores blanditiis itaque veniam 
        perferendis voluptate repellendus.`
    }
]
```

All we need to do now is to import the parent component (`accordion`) and the utilities file in the `App` component to render our static accordion.

```javascript
import Accordion from "./Accordion";
import { accordionData } from "./Utilities";
import './Style.css'


function App() {
  const items = accordionData;

  return (
   <div>
      <Accordion 
        items={items}
      />
   </div>
  );
}

export default App;
```

As you can see. Here we created an `items` variable that points to the accordion data and passed it down to `<Accordion />`

We are done writing the UI. At this point, we have a static accordion component. It is best to always write the UI first before logic and event handlers.

### Create logic and event handlers

We go back to our `Accordion` and create the state using `useState` hook and the event handler.

```javascript
function Accordion({ items }) {
    const [activeIndex, setActiveIndex] = useState(null)

    function handleClick(index) {
        setActiveIndex(activeIndex === index ? null : index)
    }

    return(
        <div>
            <Heading />

            {items.map((item, index) => (
                <AccordionItem 
                    key={index}
                    item={item}
                    isActive={index === activeIndex}
                    onToggle={() => handleClick(index)}
                />
            ))}
        </div>
    )
}
```

I created the state variables `[activeIndex, setActiveIndex]` and the handleClick function to toggle the `activeIndex` that expands or collapses the accordion. If the clicked item is the currently active one, it sets `activeIndex` to null (collapsing the item), otherwise, it sets `activeIndex` to the index of the clicked item.

In the return statement, we are returning the `<Heading />` of the app and we are also mapping over the array of `AccordionItem` components. Each `AccordionItem` receives the following props: **key**, **item**, **isActive** and **onToggle**.

```javascript
function AccordionItem({ item, isActive, onToggle}) {
    const {subject, question, answer} = item

    return (
        
        <div className="container">
             <AccordionQuestion
                 subject={subject}
                 question={question}
                 onToggle={onToggle}
                 isActive={isActive}
             />
             <AccordionAnswer
                 answer={answer}
                 isActive={isActive}
             />
        </div>
       
    )
}
```

I used a destructuring assignment to get our subject, question and answer properties from the array of objects.

```javascript
function AccordionItem({ item, isActive, onToggle}) {
    const {subject, question, answer} = item
```

```javascript
function AccordionAnswer({ answer, isActive }) {
    return (
        <>
            {isActive && <p>{answer}</p>}
        </>
    )
}

function AccordionQuestion({ subject, question, onToggle, isActive}) {
    return (
        <div className="header">
                <h2>{subject}</h2>
            <div className="subtitle" onClick={onToggle}>
                <p>{question}</p>
                <span>{ isActive ? '-' : '+'}</span>
            </div>
        </div>
    )
}
```

In the `AccordionAnswer` we pass in the **answer** and **isActive** props. It conditionally renders the answer only if the item is active (isActive is true).

The `AccordionQuestion` renders the question and toggle button of an accordion item.

### The complete code

The Accordion component

```javascript
import { useState } from "react";

function AccordionAnswer({ answer, isActive }) {
    return (
        <>
            {isActive && <p>{answer}</p>}
        </>
    )
}

function AccordionQuestion({ subject, question, onToggle, isActive}) {
    return (
        <div className="header">
                <h2>{subject}</h2>
            <div className="subtitle" onClick={onToggle}>
                <p>{question}</p>
                <span>{ isActive ? '-' : '+'}</span>
            </div>
        </div>
    )
}

function Heading() {
    return (
        <h1 className="heading">Accordion</h1>
    )
  }

function AccordionItem({ item, isActive, onToggle}) {

    const {subject, question, answer} = item

    return (
        
        <div className="container">
             <AccordionQuestion
                 subject={subject}
                 question={question}
                 onToggle={onToggle}
                 isActive={isActive}
             />
             <AccordionAnswer
                 answer={answer}
                 isActive={isActive}
             />
        </div>
       
    )
}

function Accordion({ items }) {
    const [activeIndex, setActiveIndex] = useState(null)

    function handleClick(index) {
        setActiveIndex(activeIndex === index ? null : index)
    }

    return(
        <div>
            <Heading />

            {items.map((item, index) => (
                <AccordionItem 
                    key={index}
                    item={item}
                    isActive={index === activeIndex}
                    onToggle={() => handleClick(index)}
                />
            ))}
        </div>
    )
}

export default Accordion
```

The App component

```javascript
import Accordion from "./Accordion";
import { accordionData } from "./Utilities";
import './Style.css'


function App() {
  
  const items = accordionData;

  return (
   <div>
      <Accordion 
        items={items}
      />
   </div>
  );
}

export default App;
```

And we are done.
