在React组件中重用不同子项的模态

时间:2018-06-14 21:27:15

标签: javascript reactjs modal-dialog

最近我不得不在React中写一些东西,这要求我在一个模态中渲染不同的组件。因为我不想在同一个父组件中用不同的模态重复我的自我,所以我决定重复使用它,但不确定如何正确地执行它#34;正确"。这就是我所做的:

  renderModalTitle = () => {
return this.state.currentModalAction === 'delete' ? `Are you sure you want to delete book "${this.state.currentBook.title}"?`
  : this.state.currentBook ? `Edit book "${this.state.currentBook.title}"`
    : 'Create new book'
}

renderModalBody = () => {
  return this.state.currentModalAction === 'edit' || 
   this.state.currentModalAction === 'new' ?
    <BookForm book={this.state.currentBook} onSave={this.onBookSave}> 
    </BookForm>
      : <ConfirmDelete onBookDeleteCancel={this.toggle} onBookDelete={()=> 
      {this.onBookDelete(this.state.currentBook.id)}} data= 
    {this.state.currentBook}></ConfirmDelete>

 }

我知道它有点难以阅读,因为代码片段中的缩进略微搞砸了。但正如你所看到的,根据&#34; currentModalAction&#34;我只有返回相关jsx的函数。然后在模态中:

 <Modal isOpen={this.state.modal} toggle={this.toggle} className={this.props.className}>
        <ModalHeader className="color_main" toggle={this.toggle}>{this.renderModalTitle()}</ModalHeader>
        <ModalBody>
          {this.renderModalBody()}
        </ModalBody>
        <ModalFooter>

          <Button className="square" color="default" onClick={this.toggle}>Cancel</Button>
        </ModalFooter>
      </Modal>

是的,我已经实现了可重用性&#34;这种模式,并没有重复我的自我,但在我看来,这可能弊大于利......不可读,不太清楚。

对此问题有一些共同的方法吗?请注意,我没有使用react-modal或类似的东西。它只是反应堆。

1 个答案:

答案 0 :(得分:3)

我制作了一些代表你案件的代码。

你可以使用像renderBodyComponent这样的函数道具来渲染你的模态体。

&#13;
&#13;
class FlexibleModal extends React.Component {
  render() {
    if (!this.props.isOpen) {
      return null;
    }
 
    return (
      <div className="flexible-modal">
        <div className="flexible-modal-header">
          {this.props.headerTitle}
        </div>
        <div className="flexible-modal-body">
          {this.props.renderBodyComponent()}
        </div>
      </div>
    );
  }
};

const BodyCase1 = () => (
  <div>
    Modal Body Case 1
  </div>
);

const BodyCase2 = () => (
  <div>
    Modal Body Case 2
  </div>
);

class App extends React.Component {
  
  state = {
    showModal: false,
    case: 1,
  }
 
  toggleModal = () => {
    this.setState({ showModal: !this.state.showModal });
  }
  
  toggleCase = () => {
    const nextCase = this.state.case === 1 ? 2 : 1;
    this.setState({ case: nextCase });
  }

  render() {
    return (
      <div>
        <button
          onClick={() => this.toggleModal()}
        >
          Toggle modal
        </button>
        
        <button
          onClick={() => this.toggleCase()}
        >
          Toggle next case
        </button>

        <FlexibleModal
          isOpen={this.state.showModal}
          headerTitle="Customizable Modal Header Title"
          renderBodyComponent={
            this.state.case === 1
            ? () => (<BodyCase1 />)
            : () => (<BodyCase2 />)
          }
        />
      </div>
    );
  }
}

ReactDOM.render(<App />, document.getElementById('react'));
&#13;
.flexible-modal {
  margin: 15px;
  border: 1px solid #ddd;
  background: #fff;
}

.flexible-modal-header {
  border-bottom: 1px solid #ddd;
  padding: 10px;
  background: #e7e7e7;
}

.flexible-modal-body {
  padding: 10px;
}
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

<div id="react"></div>
&#13;
&#13;
&#13;