手风琴项目重复

时间:2018-10-27 14:11:24

标签: javascript reactjs

我正在尝试在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

1 个答案:

答案 0 :(得分: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
});

因此,问题的根源在于您将父道具扩展为包括childrenheader属性的子道具。您可以(如果需要)从this.props开始扩展,但是应该可以使用children覆盖null和使用header覆盖child.props.header (也许还有其他不应该进入儿童的道具)。