How you can render an accordion menu with multiple collapsible content components in ReactJS.
To render an accordion menu with multiple collapsible content components, you need to follow the explanations below:
Define an
AccordionItem
component, pass it to the Accordion and remove unnecessary nodes expect forAccordionItem
by identifying the function's name inprops.children
.Each
AccordionItem
component renders a<button>
that is used to update the Accordion via theprops.handleClick
callback and the content of the component, passed down viaprops.children
, while its appearance is determined byprops.isCollapsed
and based on style.In the Accordion component, use the
React.useState()
hook to initialize the value of thebindIndex
state variable toprops.defaultIndex
.Use
Array.prototype.map
on the collected nodes to render the individual collapsible elements.
- Define
changeItem
, which will be executed when clicking an AccordionItem's<button>
.changeItem
executes the passed callback,onItemClick
and updatesbindIndex
based on the clicked element.
Code Sample:
function AccordionItem(props) {
const style = {
collapsed: {
display: 'none'
},
expanded: {
display: 'block'
},
buttonStyle: {
display: 'block',
width: '100%'
}
};
return (
<div>
<button style={style.buttonStyle} onClick={() => props.handleClick()}>
{props.label}
</button>
<div
className="collapse-content"
style={props.isCollapsed ? style.collapsed : style.expanded}
aria-expanded={props.isCollapsed}
>
{props.children}
</div>
</div>
);
}
function Accordion(props) {
const [bindIndex, setBindIndex] = React.useState(props.defaultIndex);
const changeItem = itemIndex => {
if (typeof props.onItemClick === 'function') props.onItemClick(itemIndex);
if (itemIndex !== bindIndex) setBindIndex(itemIndex);
};
const items = props.children.filter(item => item.type.name === 'AccordionItem');
return (
<div className="wrapper">
{items.map(({ props }) => (
<AccordionItem
isCollapsed={bindIndex === props.index}
label={props.label}
handleClick={() => changeItem(props.index)}
children={props.children}
/>
))}
</div>
);
}
ReactDOM.render(
<Accordion defaultIndex="1" onItemClick={console.log}>
<AccordionItem label="A" index="1">
Lorem ipsum
</AccordionItem>
<AccordionItem label="B" index="2">
Dolor sit amet
</AccordionItem>
</Accordion>,
document.getElementById('root')
);
Happy Coding!