Reactjs useAccordion Hook - How To Create And Use Accordions In React Js
Published: 2023-08-12 10:09:12


![Reactjs Accordion Hook - How To Create And Use Accordions In React Js](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q4thxzxx2fufvc0ad53k.png)

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

{% embed https://www.youtube.com/watch?v=820JNyifT5U %}

##### useAccordion.ts
```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;
```

##### Accorion.tsx
```ts
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>
    )
}
```

##### AccordionBody.tsx
```ts
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>
    )
}
```

##### AccordionHeader.tsx
```ts
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])
}
```

##### App.tsx
```ts
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>
    )
}
```

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

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