当前位置:   article > 正文

Antd 中Modal和Form配合时验证器无效和默认值不更新问题_a-modal @ok不触发

a-modal @ok不触发

Antd 中Modal和Form配合时验证器无效和默认值不更新问题

验证器无效问题

发现过程

在跟着B站React实战课程走的时候,因为课程是Antd V3我使用的是V4。所以在遇到Modal中嵌套From时,课程使用的是高阶组件的方式实现验证器。我看见V4直接有rules(包括使用validator)属性,直接设置后发现无效。

解决方法

其实在官方文档有Modal组件配合的实例。

import React, { useState } from 'react';
import { Button, Modal, Form, Input, Radio } from 'antd';

interface Values {
  title: string;
  description: string;
  modifier: string;
}

interface CollectionCreateFormProps {
  visible: boolean;
  onCreate: (values: Values) => void;
  onCancel: () => void;
}

const CollectionCreateForm: React.FC<CollectionCreateFormProps> = ({
  visible,
  onCreate,
  onCancel,
}) => {
  const [form] = Form.useForm();
  return (
    <Modal
      visible={visible}
      title="Create a new collection"
      okText="Create"
      cancelText="Cancel"
      onCancel={onCancel}
      onOk={() => {
        form
          .validateFields()
          .then(values => {
            form.resetFields();
            onCreate(values);
          })
          .catch(info => {
            console.log('Validate Failed:', info);
          });
      }}
    >
      <Form
        form={form}
        layout="vertical"
        name="form_in_modal"
        initialValues={{ modifier: 'public' }}
      >
        <Form.Item
          name="title"
          label="Title"
          rules={[{ required: true, message: 'Please input the title of collection!' }]}
        >
          <Input />
        </Form.Item>
        <Form.Item name="description" label="Description">
          <Input type="textarea" />
        </Form.Item>
        <Form.Item name="modifier" className="collection-create-form_last-form-item">
          <Radio.Group>
            <Radio value="public">Public</Radio>
            <Radio value="private">Private</Radio>
          </Radio.Group>
        </Form.Item>
      </Form>
    </Modal>
  );
};

const CollectionsPage = () => {
  const [visible, setVisible] = useState(false);

  const onCreate = values => {
    console.log('Received values of form: ', values);
    setVisible(false);
  };

  return (
    <div>
      <Button
        type="primary"
        onClick={() => {
          setVisible(true);
        }}
      >
        New Collection
      </Button>
      <CollectionCreateForm
        visible={visible}
        onCreate={onCreate}
        onCancel={() => {
          setVisible(false);
        }}
      />
    </div>
  );
};

ReactDOM.render(<CollectionsPage />, mountNode);
.collection-create-form_last-form-item {
  margin-bottom: 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100

CollectionCreateForm 时最关键的部分,这里使用里Reacthook语法。我通过一些更改把它还是变成了封装一个类(感觉这样也不好)。

代码如下:

import { Form, Modal } from 'antd';
import React, { Component } from 'react';
import { ICategory } from './DataModel';
import { ModalStatusCode } from './ModalStatusCode';

interface Values {
	title: string;
	description: string;
	modifier: string;
}

interface ModalFromProps {
	showStatus: ModalStatusCode;
	onCancel: () => void;
	category: ICategory;
	element: React.ReactNode;
	expectedStatus: ModalStatusCode;
	title: string;
}

interface ModalState {
	name: string;
}

class ModalForm extends Component<ModalFromProps, ModalState> {


	constructor(props: ModalFromProps) {
		super(props);
		this.state = {
			name: '',
		};
	}

	private onCancel = () => {
		this.props.onCancel();
	};


	private CreateModalFrom = (): any => {
    const [form] = Form.useForm();
		const { title } = this.props;
		return (
			<Modal
				visible={this.props.showStatus === this.props.expectedStatus}
				title={title}
				okText="Ok"
				cancelText="Cancel"
				onCancel={this.onCancel}
				onOk={() => {
					form
						.validateFields()
						.then((values) => {
							form.resetFields();
							console.log(values);
						})
						.catch((info) => {
							console.log('Validate Failed:', info);
						});
				}}
			>
				<Form form={form}>
					<Form.Item name="title" rules={[{ required: true, message: '请输入品类名称' }]} initialValue={this.props.category.name} >
						{this.props.element}
					</Form.Item>
				</Form>
			</Modal>
		);
	};

	render() {
		return <this.CreateModalFrom />;
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74

因为是React新手,所以还是凭着自己理解去封装。这样导致自定义ModalForm组件为了得到某些值必须经过某个中间组件去传,看起来就很难看且值没有任何更改,很难看。希望各位也能给个好建议。

调用ModalForm代码:

interface IUpdateFormProps {
	category: ICategory;
	onCancel: () => void;
	showStatus: ModalStatusCode;
}

interface IUpdateFormState {
}

export default class UpdateFrom extends Component<IUpdateFormProps, IUpdateFormState> {

  

	render() {

		return (
			<ModalForm {...this.props} element={<Input placeholder="请输入分类名称"></Input>} expectedStatus={ModalStatusCode.Update} title='更新分类'></ModalForm>
		);
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

对应页面上有一个列表,列表有一个修改功能。点击之后Form的input框里面显示该行属性名称。但是奇怪的是这样写名称会不更新。始终是第一个点击那一行,尝试后发现点击OK按钮名称会更新。查看代码后发现是

form.resetFields();
  • 1

起的作用,因此想着每次都调用这个方法,但尝试一番无果。晚上再去看Modal的官方文档后发现这么一句话。

<Modal /> 默认关闭后状态不会自动清空, 如果希望每次打开都是新内容,请设置 destroyOnClose。

<Modal /> 和 Form 一起配合使用时,设置 destroyOnClose 也不会在 Modal 关闭时销毁表单字段数据,
需要设置 <Form preserve={false} />。

  • 1
  • 2
  • 3
  • 4
  • 5

于是想着能不能每次打开都是重新渲染,解决这个问题。于是在添加上面的属性后便解决了问题。

思考

虽然解决了问题但是感觉有更好解决方案或者另一种实现方法,如果能还希望不吝赐教。

随笔

从偶然的出生,到必然的死亡,我们都将经历孤独和徘徊。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/115649
推荐阅读
相关标签
  

闽ICP备14008679号