代码之家  ›  专栏  ›  技术社区  ›  milan

手风琴项目重复

  •  0
  • milan  · 技术社区  · 8 年前

    我正在尝试在codesandbox中创建嵌套的accordion,以便对react有更多的了解。我能演奏那套手风琴。手风琴也可以打开或关闭。然而,手风琴是重复的。

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

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

    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 回复  |  直到 8 年前
        1
  •  1
  •   extempl    8 年前

    这个街区

    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 ,但应该在开始时就可以覆盖 儿童 具有 null 和 收割台 具有 child.props.header