说我有一个模板模态反应组件,如下所示(简化了我的问题,使其变得更加清晰):

function Modal(props) {
    const hide=()=>{
        document.querySelector('#modal').style.display='none';
    };

    return (
        <div id = 'modal' className='modal'>
           {props.children}
           //close button and so on...
        </div>
    );
}

export default Modal;


现在,我将为特定目的制作模态的更特定版本。因此,我传递了Modal功能组件children,它们将是AreYouSureModal的孙代:

function AreYouSureModal(props) {

    yesAction = ()=>{props.yesAction}
    noAction = ()=>{props.noAction}
    const children = <fragment>
        Are you sure?
        <button onclick = {this.yesAction /*and call .hide() in Modal*/}>Yes</button>
        <button onclick = {this.noAction /*and call .hide() in Modal*/}>No</button>
    </fragment>;

    return <Modal children = {children} />
}

export default AreYouSureModal;


现在yesActionnoAction将会是我从AreYouSureModal父级那里获得的东西,所以我要传递这些函数。但是这些按钮还需要调用模板hide()功能组件中的Modal函数。做这个的最好方式是什么?

我是否可以在yesActionAreYouSureModal函数中调用Modal子级的方法?还是在Modal函数中使AreYouSureModal成为常量并将这些方法绑定到该常量之前,将其传递给我?

换句话说,我该如何创建在子代中调用函数的孙子代?还是我完全以完全错误的方式尝试执行此操作?

最佳答案

我建议不要使用样式来隐藏模态,而建议使用React Portals。免责声明:我还没有使用钩子,所以我将使用类组件来编写它。

无论如何,您的Modal-组件将如下所示:

class Modal extends React.Component {
  render() {
    if (!this.props.isOpen) return null

    return (
      ReactDOM.createPortal(
        <div className="modal">
          {this.props.children}
        </div>
      )
    )
  }
}


然后,您的AreYouSureModal-组件将如下所示:

class AreYouSureModal extends React.Component {
  handleYesAction = () => {
    /* Do something */
    this.props.onClose()
  }

  handleNoAction = () => {
    /* Do something */
    this.props.onClose()
  }

  render() {
    return (
      <Modal isOpen={this.props.isOpen}>
        <React.Fragment>
          <h2>Are you sure?</h2>
          <button onClick={this.handleYesAction}>Yes</button>
          <button onClick={this.handleNoAction}>No</button>
         </React.Fragment>
      </Modal>
    )
  }
}


最后,从中呈现AreYouSureModal的组件将保留模态的状态:

class App extends React.Component {
  state = { isAreYouSureModalOpen: false }

  openAreYouSureModal = () => this.setState({ isAreYouSureModalOpen: true })

  closeAreYouSureModal = () => this.setState({ isAreYouSureModalOpen: false })

  render() {
    return (
      <React.Fragment>
        <button onClick={this.openAreYouSureModal}>Open modal</button>

        <AreYouSureModal
          onClose={this.closeAreYouSureModal}
          isOpen={this.state.isAreYouSureModalOpen}
        />
      </React.Fragment>
    )
  }
}

09-25 18:52