【问题标题】:accordion items are repeated手风琴项目重复
【发布时间】:2018-10-27 14:11:23
【问题描述】:

我正在尝试在代码和框中创建嵌套手风琴,以获得对反应的更多了解。我可以渲染嵌套的手风琴。手风琴也可以打开和关闭。然而手风琴是重复的。

我创建了一个沙箱来展示工作示例

手风琴.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

【问题讨论】:

    标签: javascript reactjs


    【解决方案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 扩展,但应该在一开始就能够用null 覆盖children 和用child.props.header 覆盖header(也许还有其他不应该得到的道具也适用于儿童)。

    【讨论】:

      猜你喜欢
      • 2022-11-11
      • 2019-11-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-26
      • 1970-01-01
      相关资源
      最近更新 更多