import "./index.css"; import React, { Component } from "react"; class Accordion extends Component { static defaultProps = { onChange: () => {}, statusIconsComponents: { opened: "▲", closed: "▼" }, allowMultipleExpand: true }; state = { activeIndexes: [] }; updateIndexes = (index, callback) => { const { allowMultipleExpand, onChange } = this.props; this.setState(prevState => { let activeIndexes; let isOpen = false; if (prevState.activeIndexes.includes(index)) { activeIndexes = allowMultipleExpand ? prevState.activeIndexes.filter( currentIndex => currentIndex !== index ) : []; } else { isOpen = true; activeIndexes = allowMultipleExpand ? prevState.activeIndexes.concat(index) : [index]; } callback(isOpen); onChange(activeIndexes); return { activeIndexes }; }); }; render() { const children = React.Children.map(this.props.children, (child, index) => { const isActive = this.state.activeIndexes.includes(index); return React.cloneElement(child, { isActive, statusIcon: this.props.statusIconsComponents[ isActive ? "opened" : "closed" ], onSelect: onSelectCallback => this.updateIndexes(index, onSelectCallback) }); }); return
{children}
; } } class AccordionItem extends Component { static defaultProps = { onChange: () => {}, isOpen: false }; componentWillMount() { const { isOpen, onSelect, onChange } = this.props; if (isOpen) { onSelect(onChange); } } render() { const { isActive, statusIcon, onSelect, onChange } = this.props; const children = React.Children.map(this.props.children, child => { return React.cloneElement(child, { isActive, statusIcon, onSelect: () => { onSelect(onChange); } }); }); return
{children}
; } } class AccordionHeader extends Component { render() { return (
{this.props.children} - {this.props.statusIcon}
); } } class AccordionPanel extends Component { render() { return this.props.isActive ? (
{this.props.children}
) : null; } } class App extends Component { render() { return (
console.log("isOpen = ", isOpen)} > Header 1 Panel 1 Header 2 Panel 2 Header 3 Panel 3
); } } export default App;