A Step-by-Step Guide to Building an Accordion in ReactJS

In modern web applications, user experience is important. When dealing with pages that require users to fill out multiple forms, such as a profile settings page, a multi-step checkout, or a complex application form, presenting them all at once can be challenging. This is where an accordion component is beneficial. It allows for the organization of content into collapsible sections, presenting one form at a time while keeping the others neatly hidden.

In this guide, we will explore how to build a functional and reusable accordion component in ReactJS that can accommodate multiple forms on a single page, improving both aesthetics and usability.

Let’s break down the logic:

The Accordion Component: The State Manager

// File: js/Components/Accordion.jsx

import React, { useState } from 'react';
import AccordionItem from '@/Components/AccordionItem';

const Accordion = ({ items }) => {
    const [openItemId, setOpenItemId] = useState(null);

    const handleClick = (id) => {
        setOpenItemId(prev => (prev === id ? null : id));
    };

    return (
        <div className="accordion">
            {items.map(item => (
                <AccordionItem
                    key={item.id}
                    item={item}
                    isOpen={item.id === openItemId}
                    onClick={handleClick}
                />
            ))}
        </div>
    );
};

export default Accordion;

 

The AccordionItem Component: The Collapsible Panel

// File: js/Components/AccordionItem.jsx

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

const AccordionItem = React.memo(({ item, isOpen, onClick }) => {
    return (
        <div className="border shadow-lg rounded-xl bg-white p-4 mb-3 shadow sm:rounded-lg sm:p-8">
            <button onClick={() => onClick(item.id)} className="w-full">
                <h2 className="text-xl font-medium text-gray-900 hover:text-[#ff3131] flex items-center justify-between">
                    {item.title} {isOpen ? <FaChevronUp/> : <FaChevronDown/>}
                </h2>
            </button>
            {isOpen && <div>{item.content}</div>}
        </div>
    );
}, (prevProps, nextProps) => {
    // Prevent re-render unless isOpen or item changes
    return (
        prevProps.isOpen === nextProps.isOpen &&
        prevProps.item.id === nextProps.item.id &&
        prevProps.item.title === nextProps.item.title &&
        prevProps.item.content === nextProps.item.content
    );
});

export default AccordionItem;

 

The Form Components: Your Business Logic

// File: js/Components/Edit.jsx

import React from 'react';
import { Head } from '@inertiajs/react';
import Accordion from "@/Components/Accordion";
import Tab1Component from "@/Components/Forms/Tab1Component";
import Tab2Component from "@/Components/Forms/Tab2Component";
import Tab3Component from "@/Components/Forms/Tab3Component";
import Tab4Component from "@/Components/Forms/Tab4Component";
import Tab5Component from "@/Components/Forms/Tab5Component";

export default function Edit() {
    const items = [
        { id: 1, title: 'Tab1', content: <Tab1Component className="w-full" /> },
        { id: 2, title: 'Tab2', content: <Tab2Component className="w-full" /> },
        { id: 3, title: 'Tab3', content: <Tab3Component className="w-full" /> },
        { id: 4, title: 'Tab4', content: <Tab4Component className="w-full" /> },
        { id: 5, title: 'Tab5', content: <Tab5Component className="w-full" /> }
    ];

    return (
        <div>
            <Head title="Users Edit Form"/>

            <div className="py-4 px-2 sm:py-12 sm:px-0">
                <div className="mx-auto max-w-7xl space-y-6 sm:px-6 lg:px-8">
                    <h1>User Edit Form</h1>
                    <Accordion items={items}/>
                </div>
            </div>
        </div>
    );
}
// File: js/Components/Forms/Tab1Component.jsx

export default function Tab1Component({className = ''}) {
    return (
        <section className={className}>
            // Tab1Component Form Content
        </section>
    );
}

Tab1Component is used as an example; it can be replaced with your specific form components. The same applies to Tab2Component, Tab3Component, and subsequent tabs.

This pattern not only helps to create a more organized and inviting UI but also makes your forms feel more approachable and user-friendly. By doing so, it encourages users to complete them with ease, ultimately fostering better engagement and conversion rates.

We hope this blog may be understandable and useful to you. You can email us at mage2developer@gmail.com if we missed anything or if you want to add any suggestions. We will respond to you as soon as possible. Happy to help 🙂

Need Further Help? or Questions?

Contact Us

Create your account

chatsimple