2.5 KiB
2.5 KiB
title, tags
| title | tags |
|---|---|
| Accordion | components,children,state,advanced |
Renders an accordion menu with multiple collapsible content components.
- Define an
AccordionItemcomponent, pass it to theAccordionand remove unnecessary nodes expect forAccordionItemby identifying the function's name inchildren. - Each
AccordionItemcomponent renders a<button>that is used to update theAccordionvia thehandleClickcallback and the content of the component, passed down viachildren, while its appearance is determined byisCollapsedand based onstyle. - In the
Accordioncomponent, use theReact.useState()hook to initialize the value of thebindIndexstate variable todefaultIndex. - Use
Array.prototype.map()on the collected nodes to render the individual collapsiple elements. - Define
changeItem, which will be executed when clicking anAccordionItem's<button>.changeItemexecutes the passed callback,onItemClickand updatesbindIndexbased on the clicked element.
const AccordionItem = ({ label, isCollapsed, handleClick, children }) => {
const style = {
collapsed: {
display: 'none'
},
expanded: {
display: 'block'
},
buttonStyle: {
display: 'block',
width: '100%'
}
};
return (
<div>
<button style={style.buttonStyle} onClick={handleClick}>
{label}
</button>
<div
className="collapse-content"
style={isCollapsed ? style.collapsed : style.expanded}
aria-expanded={isCollapsed}
>
{children}
</div>
</div>
);
};
const Accordion = ({ defaultIndex, onItemClick, children }) => {
const [bindIndex, setBindIndex] = React.useState(defaultIndex);
const changeItem = itemIndex => {
if (typeof onItemClick === 'function') onItemClick(itemIndex);
if (itemIndex !== bindIndex) setBindIndex(itemIndex);
};
const items = 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')
);