DEV Community

GihanRangana
GihanRangana

Posted on

Reactjs useAccordion Hook - How To Create And Use Accordions In React Js

Reactjs Accordion Hook - How To Create And Use Accordions In React Js

Unlock streamlined content organization in ReactJS with our in-depth tutorial on creating and utilizing custom Accordion Hooks. Elevate user experience by mastering the process of crafting and integrating accordions seamlessly into your React applications. Perfect for developers seeking efficient UI/UX solutions.

Follow this tutorial to create your own useAccordion hook in react js

useAccordion.ts
import { useState, useEffect, useCallback, useMemo } from "react"

const useAccordion = (steps: StepsType[], activeName: string): UseAccordionType => {

    const [activeIndex, setActiveIndex] = useState<number>(0)
    const [currentStep, setCurrentStep] = useState<StepsType>(steps[0])

    useEffect(() => {
        if (!activeName) return;

        steps.map((step, index) => {
            if (step.name === activeName) {
                setActiveIndex(index)
                setCurrentStep(step)
            }
        })

    }, [])

    const goNext = () => setActiveIndex((next) => next < steps.length ? next + 1 : steps.length)
    const goPrev = () => setActiveIndex((prev) => prev > 0 ? prev - 1 : 0)

    const handleHeaderClick = (index: number) => {
        setActiveIndex(index)
        setCurrentStep(steps[index])
    }

    const isActive = useCallback((index: number) => {
        return index === activeIndex
    }, [activeIndex])

    return useMemo(() => ({
        steps,
        activeIndex,
        currentStep,
        goNext,
        goPrev,
        handleHeaderClick,
        isActive
    }), [activeIndex, currentStep])
}

export default useAccordion;
Enter fullscreen mode Exit fullscreen mode
Accorion.tsx
const Accordion: React.FC<AccordionProps> = (props) => {

    const { steps } = props

    const renderContent = (step: StepsType, index: number) => {

        return (
            <React.Fragment key={`accordion-${index.toString()}-${step.name}`}>
                <div className={styles.accordionItem}>

                    <AccordionHeader {...props} step={step} index={index} />

                    <AccordionBody {...props} step={step} index={index} />

                </div>
            </React.Fragment>
        )
    }

    return (
        <div className={styles.accordion}>
            {steps && steps.map((step, index) => renderContent(step, index))}
        </div>
    )
}
Enter fullscreen mode Exit fullscreen mode
AccordionBody.tsx
const AccordionBody: React.FC<AccordionBodyProps> = (props) => {

    const { activeIndex, step, index } = props;

    const getClassNames = () => {

        const classes: string[] = [styles.accordionBody]

        if (activeIndex === index) classes.push(styles.active)

        return classes.join(' ')
    }

    return (
        <div
            className={getClassNames()}
        >
            {step.render && step.render(step)}
        </div>
    )
}
Enter fullscreen mode Exit fullscreen mode
AccordionHeader.tsx
const AccordionHeader: React.FC<AccordionHeaderProps> = (props) => {

    const { activeIndex, step, handleHeaderClick, index, isActive } = props

    const getClassNames = () => {

        const classes: string[] = [styles.accordionHeader]

        if (activeIndex === index) classes.push(styles.active)

        return classes.join(' ')
    }

    return useMemo(() => (
        <div
            className={getClassNames()}
            onClick={handleHeaderClick.bind(null, index)}
        >
            <span>{step.title}</span>

            <IoChevronForwardSharp
                className={[
                    styles.chevron,
                    isActive(index)
                        ? styles.chevronActive
                        : styles.chevronInactive
                ].join(' ')}
            />

        </div>
    ), [activeIndex])
}
Enter fullscreen mode Exit fullscreen mode
App.tsx
function App() {

    const steps: StepsType[] = [
        {
            name: "accordion1",
            title: "Accordion 1 Title",
            render: (props: any) => (
                <p>
                    {/*content*/}
                    Lorem ipsum dolor sit amet consectetur adipisicing elit. Recusandae sit quod vero corrupti ducimus iste suscipit, culpa maiores minima sunt nobis adipisci expedita aliquid voluptatibus ab facere. Earum, distinctio quidem.
                </p>
            )
        },
        {
            name: "accordion2",
            title: "Accordion 2 Title",
            render: (props: any) => (
                <p>
                    Lorem ipsum dolor sit amet consectetur adipisicing elit. Facilis, soluta quia odio dicta aspernatur vel, nesciunt repudiandae perspiciatis adipisci ipsum quae laborum minima praesentium iste modi doloremque officia saepe vitae!
                </p>
            )
        }
    ]

    const accordion = useAccordion(steps, 'accordion1')

    return (
        <div className="App">
            <Accordion {...accordion} />
        </div>
    )
}
Enter fullscreen mode Exit fullscreen mode

Follow the above video to get an idea about this source code.

Source: https://github.com/TheCodersLife/react-hook-useAccordion

Top comments (0)