在一个组件中使用多个模态形式

时间:2018-01-30 15:16:36

标签: reactjs antd

我有一个包含许多按钮的页面,并希望每个按钮在单击时打开自己的模态窗体。我有一个问题,多次使用相同的形式/模态不会导致独特的形式。例如,单击第一个按钮,然后键入" asdf"进入表单也会填充由第二个按钮控制的表单。

如何重用我的模态/表格并保持其数据不同?

我的代码:

import React from 'react';
import ReactDOM from 'react-dom';
import 'antd/dist/antd.css';
import './index.css';
import { Button, Modal, Form, Input, Radio } from 'antd';
const FormItem = Form.Item;

const CollectionCreateForm = Form.create()(
  (props) => {
    const { visible, onCancel, onCreate, form } = props;
    const { getFieldDecorator } = form;
    return (
      <Modal
        visible={visible}
        title="Create a new collection"
        okText="Create"
        onCancel={onCancel}
        onOk={onCreate}
      >
        <Form layout="vertical">
          <FormItem label="Title">
            {getFieldDecorator('title', {
              rules: [{ required: true, message: 'Please input the title of collection!' }],
            })(
              <Input />
            )}
          </FormItem>
          <FormItem label="Description">
            {getFieldDecorator('description')(<Input type="textarea" />)}
          </FormItem>
          <FormItem className="collection-create-form_last-form-item">
            {getFieldDecorator('modifier', {
              initialValue: 'public',
            })(
              <Radio.Group>
                <Radio value="public">Public</Radio>
                <Radio value="private">Private</Radio>
              </Radio.Group>
            )}
          </FormItem>
        </Form>
      </Modal>
    );
  }
);

class CollectionsPage extends React.Component {
  state = {
    visible: false,
  };
  showModal = () => {
    this.setState({ visible: true });
  }
  handleCancel = () => {
    this.setState({ visible: false });
  }
  handleCreate = () => {
    const form = this.form;
    form.validateFields((err, values) => {
      if (err) {
        return;
      }

      console.log('Received values of form: ', values);
      form.resetFields();
      this.setState({ visible: false });
    });
  }
  saveFormRef = (form) => {
    this.form = form;
  }
  render() {
    return (
      <div>
        <Button type="primary" onClick={this.showModal}>New Collection</Button>
        <CollectionCreateForm
          ref={this.saveFormRef}
          visible={this.state.visible}
          onCancel={this.handleCancel}
          onCreate={this.handleCreate}
        />
        <Button type="primary" onClick={this.showModal}>New Collection</Button>
        <CollectionCreateForm
          ref={this.saveFormRef}
          visible={this.state.visible}
          onCancel={this.handleCancel}
          onCreate={this.handleCreate}
        />
        <Button type="primary" onClick={this.showModal}>New Collection</Button>
        <CollectionCreateForm
          ref={this.saveFormRef}
          visible={this.state.visible}
          onCancel={this.handleCancel}
          onCreate={this.handleCreate}
        />
        <Button type="primary" onClick={this.showModal}>New Collection</Button>
        <CollectionCreateForm
          ref={this.saveFormRef}
          visible={this.state.visible}
          onCancel={this.handleCancel}
          onCreate={this.handleCreate}
        />
        <Button type="primary" onClick={this.showModal}>New Collection</Button>
        <CollectionCreateForm
          ref={this.saveFormRef}
          visible={this.state.visible}
          onCancel={this.handleCancel}
          onCreate={this.handleCreate}
        />
        <Button type="primary" onClick={this.showModal}>New Collection</Button>
        <CollectionCreateForm
          ref={this.saveFormRef}
          visible={this.state.visible}
          onCancel={this.handleCancel}
          onCreate={this.handleCreate}
        />
      </div>
    );
  }
}

ReactDOM.render(<CollectionsPage />, document.getElementById('container'));

interactive sandbox

1 个答案:

答案 0 :(得分:3)

问题是每个表单都有相同的道具,因此它们被视为相同的表单。在render函数中,您可以创建多个ButtonCollectionCreateForm s:

<Button type="primary" onClick={this.showModal}>New Collection</Button>
<CollectionCreateForm
  ref={this.saveFormRef}
  visible={this.state.visible}
  onCancel={this.handleCancel}
  onCreate={this.handleCreate}
/>
// repeated...

问题在于你将相同的道具传递给其中每一个。您只需设置一个ref和一个state。每个表格都是完全相同的表格。当一个模态可见时,它们全部可见。

而不是这个,你需要为每个表单保持单独的状态和引用。 (请继续阅读,不要只复制此代码......这是错误的代码。

class CollectionsPage extends React.Component {
  state = {
    visible1: false,
    visible2: false
  };
  showModal1 = () => {
    this.setState({ visible1: true });
  }
  showModal2 = () => {
    this.setState({ visible2: true });
  }
  handleCancel1 = () => {
    this.setState({ visible1: false });
  }
  handleCancel2 = () => {
    this.setState({ visible2: false });
  }
  handleCreate1 = () => {
    // ...
    this.setState({ visible1: false });
  }
  handleCreate2 = () => {
    // ...
    this.setState({ visible2: false });
  }
  saveFormRef1 = (form) => {
    this.form1 = form;
  }
  saveFormRef2 = (form) => {
    this.form2 = form;
  }
  render() {
    return (
      <div>
        <Button type="primary" onClick={this.showModal}>New Collection</Button>
        <CollectionCreateForm
          ref={this.saveFormRef1}
          visible={this.state.visible1}
          onCancel={this.handleCancel1}
          onCreate={this.handleCreate1}
        />
        <Button type="primary" onClick={this.showModal}>New Collection</Button>
        <CollectionCreateForm
          ref={this.saveFormRef2}
          visible={this.state.visible2}
          onCancel={this.handleCancel2}
          onCreate={this.handleCreate2}
        />
      </div>
    );
  }
}

我向您展示了如何解决您的问题,但这是一种很难实现的方法。随着您添加更多表格和模态,这将失控。我们可以通过将逻辑委托给子组件来改进。

首先,我们可以创建一个封装按钮&amp;的通用ModalToggle。形式/模态合二为一:

const CollectionsPage = () => (
  <div>
    <ModalToggle 
      label="New Collection"
      modal={ CollectionFormModal }
    />
    <ModalToggle 
      label="New Collection"
      modal={ CollectionFormModal }
    />
  </div>
);

我们可以通过移动所有状态来随意重用ModalToggle,这样就足够了:

class ModalToggle extends React.Component {
  state = {
    visible: false
  };
  toggleModal = () => {
    this.setState(prevState => ({ visible: !prevState.visible }));
  }
  render() {
    const Modal = this.props.modal;
    return (
      <div>
        <Button type="primary" onClick={this.toggleModal}>{this.props.label}</Button>
        <Modal
          visible={this.state.visible}
          toggleVisibility={this.toggleModal}
        />
      </div>
    );
  }
}

然后,我们只需要添加一个CollectionFormModal来处理之前CollectionsPage中的其他逻辑:

class CollectionFormModal extends React.Component {
  handleCancel = () => {
    this.props.toggleVisibility();
  }
  handleCreate = () => {
    // ...
    this.props.toggleVisibility();
  }
  render() {
    return (
      <CollectionCreateForm
        onCancel={this.handleCancel}
        onCreate={this.handleCreate}
        visible={this.props.visible}
      />
    );
  }
}

您可以将Modal的{​​{1}}部分移到CollectionCreateForm,而不是使用CollectionFormModal,将表单写成{{ref,从而进一步改善这一点。 3}}