Элементы аккордеона повторяются

Я пытаюсь создать вложенный аккордеон в 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;

для демонстрации вложенного аккордеона вот песочница

https://codesandbox.io/s/0o3x3w0yn0

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
0
113
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Этот блок

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 (возможно, также другие реквизиты, которые также не должны попадать в детей).

Другие вопросы по теме