0
0
ReactHow-ToBeginner · 4 min read

How to Create Accordion in React: Simple Step-by-Step Guide

To create an accordion in React, use a functional component with useState to track which section is open. Render clickable headers that toggle the visibility of their content by updating the state. This approach keeps the UI simple and interactive with minimal code.
📐

Syntax

An accordion in React typically uses a functional component with useState to store the index or id of the open section. Each accordion item has a clickable header that toggles its content's visibility by updating this state.

The main parts are:

  • useState: to track open/closed state
  • Click handler: toggles the open section
  • Conditional rendering: shows content only if its section is open
jsx
import React, { useState } from 'react';

function Accordion() {
  const [openIndex, setOpenIndex] = useState(null);

  const toggleIndex = (index) => {
    setOpenIndex(openIndex === index ? null : index);
  };

  return (
    <div>
      {/* Accordion items here */}
    </div>
  );
}
💻

Example

This example shows a simple accordion with three sections. Clicking a header opens its content and closes others. Clicking the open header closes it.

jsx
import React, { useState } from 'react';

function Accordion() {
  const [openIndex, setOpenIndex] = useState(null);

  const items = [
    { title: 'Section 1', content: 'Content for section 1.' },
    { title: 'Section 2', content: 'Content for section 2.' },
    { title: 'Section 3', content: 'Content for section 3.' }
  ];

  const toggleIndex = (index) => {
    setOpenIndex(openIndex === index ? null : index);
  };

  return (
    <div style={{ maxWidth: '400px', margin: '20px auto', fontFamily: 'Arial, sans-serif' }}>
      {items.map((item, index) => (
        <div key={index} style={{ border: '1px solid #ccc', marginBottom: '5px', borderRadius: '4px' }}>
          <button
            onClick={() => toggleIndex(index)}
            aria-expanded={openIndex === index}
            aria-controls={`section-content-${index}`}
            id={`section-header-${index}`}
            style={{
              width: '100%',
              padding: '10px',
              textAlign: 'left',
              background: '#f7f7f7',
              border: 'none',
              cursor: 'pointer',
              fontSize: '1rem'
            }}
          >
            {item.title}
          </button>
          {openIndex === index && (
            <div
              id={`section-content-${index}`}
              role="region"
              aria-labelledby={`section-header-${index}`}
              style={{ padding: '10px', background: '#fff' }}
            >
              {item.content}
            </div>
          )}
        </div>
      ))}
    </div>
  );
}

export default Accordion;
Output
A vertical list of three sections labeled 'Section 1', 'Section 2', and 'Section 3'. Clicking a section header expands its content below it, showing text like 'Content for section 1.'. Only one section can be open at a time. Clicking an open section closes it.
⚠️

Common Pitfalls

Common mistakes when creating accordions in React include:

  • Not managing state properly, causing multiple sections to stay open unintentionally.
  • Using indexes as keys without stable data, which can cause rendering issues.
  • Not adding accessible attributes like aria-expanded and aria-controls, which hurts keyboard and screen reader users.
  • Forgetting to toggle state correctly, so clicking an open section does not close it.
jsx
/* Wrong: Multiple sections open because state is boolean per item */

import React, { useState } from 'react';

function WrongAccordion() {
  const [open, setOpen] = useState([false, false, false]);

  const toggleIndex = (index) => {
    const newOpen = [...open];
    newOpen[index] = !newOpen[index];
    setOpen(newOpen);
  };

  return (
    <div>
      {[0,1,2].map(i => (
        <div key={i}>
          <button onClick={() => toggleIndex(i)}>Section {i + 1}</button>
          {open[i] && <div>Content {i + 1}</div>}
        </div>
      ))}
    </div>
  );
}

/* Right: Single open index state to allow only one open section */

import React, { useState } from 'react';

function RightAccordion() {
  const [openIndex, setOpenIndex] = useState(null);

  const toggleIndex = (index) => {
    setOpenIndex(openIndex === index ? null : index);
  };

  return (
    <div>
      {[0,1,2].map(i => (
        <div key={i}>
          <button onClick={() => toggleIndex(i)}>Section {i + 1}</button>
          {openIndex === i && <div>Content {i + 1}</div>}
        </div>
      ))}
    </div>
  );
}
📊

Quick Reference

  • Use useState to track which accordion section is open.
  • Toggle the open section by comparing current state with clicked index.
  • Use semantic HTML and ARIA attributes for accessibility.
  • Render content conditionally based on open state.
  • Style headers as buttons for keyboard navigation.

Key Takeaways

Use React's useState hook to track the open accordion section index.
Toggle the open section by setting state to the clicked index or null to close.
Render accordion content conditionally based on the open state for performance.
Add ARIA attributes like aria-expanded and aria-controls for accessibility.
Use button elements for headers to support keyboard navigation.