在React中,孩子如何影响父母?

时间:2019-03-15 18:28:40

标签: javascript reactjs

我遇到这样的情况:

<DropDown>
  <p>Select an option:</p>
  <button onClick={() => console.log("opt 1")}>Option 1</button>
  <button onClick={() => console.log("opt 1")}>Option 2</button>
</DropDown>

DropDown组件是我编写的,它以下拉方式呈现this.props.children。 DropDown有一个onClick调用使它关闭。

DropDown看起来像这样(简化):

class DropDown extends Component {
  state = {
    open: false
  };

  render() {
    return (
      <div className={`drop-down ${this.state.open ? "open" : "closed"}`}>
        <div className="closed-version">
          <div className="header" onClick={this.open}>
            <div className="header-contents">Click here to select an option</div>
          </div>
        </div>
        <div className="open-version">
          <div className="content" onClick={this.closeWithoutSelection}>
            {this.props.children}
          </div>
        </div>
      </div>
    );
  }

  open = () => {
    this.setState({ open: true }, () => {
      if (this.props.onOpen) {
        this.props.onOpen();
      }
    });
  };

  closeWithoutSelection = () => {
    this.setState({ open: false }, () => {
      if (this.props.onCloseWithoutSelection) {
        this.props.onCloseWithoutSelection();
      }
    });
  };
}

我遇到的问题是无论是否关闭选择选项,我都想做与DropDown不同的操作。我该怎么做?

3 个答案:

答案 0 :(得分:1)

已更新

因此@pupeno(他是对的),下拉逻辑应该在下拉菜单本身内。但是,我们应该传递一个回调函数来处理所选数据。

class DropDown extends React.Component {
  state = {
    open: false,
  };
  
  toggleDropdown = (e) => {
    this.setState({
      open: !this.state.open,
    });
    
    const value = e.target.getAttribute('value');
    
    if ( value !== "null") {
      this.props.selectItem(value);
    }
  };
  
  render() {
    const { selectItem } = this.props;
    const { open } = this.state;
    
    return (
      <div className={open ? "drop-down open" : "drop-down"}>
        <div onClick={this.toggleDropdown} value="null">Select</div>
        <div onClick={this.toggleDropdown} value="1">Item 1</div>
        <div onClick={this.toggleDropdown} value="2">Item 2</div>
        <div onClick={this.toggleDropdown} value="3">Item 3</div>
      </div> 
    );
  }
};

class App extends React.Component {
  requestItem = (item) => {
    alert(`Request item ${item}`);
  };
  
  render() {
    return (
      <div>
        <DropDown selectItem={this.requestItem}/>
      </div>
    );
  }
}

ReactDOM.render(
  <App />,
  document.querySelector('#app')
);
.drop-down {
  border: 1px solid black;
  width: 180px;
  height: 30px;
  overflow: hidden;
  transition: height 0.3s ease;
}

.open {
  height: 120px;
}

.drop-down > div {
  padding: 5px;
  box-sizing: border-box;
  height: 30px;
  border-bottom: 1px solid black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="app"></div>

答案 1 :(得分:1)

在您的DropDown组件中,您有一些状态,您可能会像这样渲染孩子:

this.props.children

相反,您可以使用render props将状态,方法或其他任何东西传递给孩子,而不必在父级的DropDown组件之外进行处理。

class DropDown extends Component {
  // constructor / state, methods...

  yourSpecialMethod(item) {
    // do your special thing here
  }

  render() {
    // pass state or methods down to children!
    return this.props.children(yourSpecialMethod)
  }
}

然后稍微修改渲染效果:

<DropDown>
  {handleSpecialMethod =>
    <>
      <p>Select an option:</p>
      <button onClick={() => handleSpecialMethod("opt 1")}>Option 1</button>
      <button onClick={() => handleSpecialMethod("opt 1")}>Option 2</button>
    </>
  }
</DropDown>

答案 2 :(得分:0)

您可以使用onChange函数并调用作为prop传递的父函数。根据您的要求,这将“影响父母”。

this.props.onChange()或类似的内容。