Я пытаюсь создать вложенный аккордеон в codeandbox, чтобы получить больше информации о реакции. Я мог отрендерить вложенный аккордеон. Аккордеон открывается и закрывается. Однако гармошка повторяется.
Я создал песочницу, чтобы показать рабочий пример
Accordion.js
class Accordion extends React.Component {
constructor(props) {
super(props);
let state = { activeSections: {} };
React.Children.toArray(props.children).forEach(child => {
if (child) {
state.activeSections[child.props.name] = !!child.props.defaultOpen;
}
});
this.state = state;
}
get isControlled() {
return typeof this.props.onToggle === "function";
}
onToggle = name => {
if (this.isControlled) {
this.props.onToggle(name);
} else {
let activeSections = this.state.activeSections;
this.setState({
activeSections: { ...activeSections, [name]: !activeSections[name] }
});
}
};
componentWillReceiveProps(nextProps) {
let { activeSections } = this.state;
React.Children.toArray(nextProps.children)
.filter(c => c)
.forEach(child => {
if (activeSections[child.props.name] == null) {
activeSections[child.props.name] = !!child.props.defaultOpen;
}
});
this.setState({ activeSections });
}
render() {
let { activeSections } = this.state;
let children = React.Children.toArray(this.props.children);
return (
<div>
{children.map(child => {
if (!child) {
return child;
} else if (child.type === AccordionItem) {
return React.cloneElement(child, {
expanded: this.isControlled
? child.props.expanded
: activeSections[child.props.name],
onToggle: this.onToggle,
...this.props
});
} else {
return child;
}
})}
</div>
);
}
}
AccordionItem.js
class AccordionItem extends React.Component {
render() {
let {
expanded,
caption,
onToggle,
name,
children,
render,
...rest
} = this.props;
return render ? (
render({ onToggle: onToggle.bind(null, name), expanded })
) : (
<styled.AccordionItem style = {{ margin: 10 }}>
<styled.AccordionHeader
onClick = {() => onToggle(name)}
active = {expanded}
>
{caption}
</styled.AccordionHeader>
<styled.AccordionBody active = {rest.defaultOpen || expanded}>
{children && (
<styled.AccordionBodyContent>
{children}
</styled.AccordionBodyContent>
)}
</styled.AccordionBody>
</styled.AccordionItem>
);
}
}
export default AccordionItem;
для демонстрации вложенного аккордеона вот песочница



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Этот блок
return React.cloneElement(child, {
expanded: this.isControlled
? child.props.expanded
: activeSections[child.props.name],
onToggle: this.onToggle,
...this.props
});
Должно выглядеть так:
return React.cloneElement(child, {
expanded: this.isControlled
? child.props.expanded
: activeSections[child.props.name],
onToggle: this.onToggle
});
Итак, корень проблемы в том, что вы расширяете родительские свойства на дочерние, включая свойства children и header. Вы можете (если вам нужно) расширить this.props, но это должно быть в начале, чтобы иметь возможность перезаписывать children на null и header на child.props.header (возможно, также другие реквизиты, которые также не должны попадать в детей).