简体   繁体   English

React Ant 设计 form.resetFields() 不调用 onChange 事件<form.items></form.items>

[英]React Ant Design form.resetFields() doesn't call onChange event of <Form.Items>

I'm having an Ant Design <Form> component with <Form.Items> which have onChange events.我有一个 Ant 设计<Form>组件与<Form.Items>有 onChange 事件。 If the onChange event function is true I'm displaying extra content.如果 onChange 事件 function 为真,我将显示额外的内容。 So in the example sandbox I created, when changing all the the <Radio> to Yes it fires the onChange event which is validated and then showing a div with the text "You checked all answered with yes".因此,在我创建的示例沙箱中,当将所有<Radio>更改为 Yes 时,它会触发经过验证的 onChange 事件,然后显示一个带有文本“你检查了所有答案为是”的 div。 As I'm using <Form> it is a form controlled environment so I'm using form to set and reset values.当我使用<Form>时,它是一个表单控制的环境,所以我使用form来设置和重置值。 But when calling form.resetFields() the onChange handlers are not called.但是在调用form.resetFields()时不会调用 onChange 处理程序。 So the message won't go away as the state not refreshes.因此,由于 state 未刷新,因此消息不会 go 消失。 So I have to find a way to call a function from the parent component which refreshes the form values in the child component.所以我必须想办法从父组件中调用 function 来刷新子组件中的表单值。 Using useImperativeHandle() for every field to update on more complex forms to call functions from the parent seems way too complex for such a simple task.对每个字段使用useImperativeHandle()来更新更复杂的 forms 以从父级调用函数对于这样一个简单的任务来说似乎太复杂了。 And adding custom events to communicate with parent components seem to be a not very react way when reading this stack overflow thread Is there something from the Ant Design form I'm missing?并且在阅读此堆栈溢出线程时添加自定义事件以与父组件进行通信似乎不是很反应的方式我缺少 Ant 设计表单中的某些内容吗? Because this must be a common task.因为这一定是一项共同的任务。 What's a good way to approach this problem?解决这个问题的好方法是什么?

Link to code sandbox with an example:通过示例链接到代码沙箱:

https://codesandbox.io/s/vigilant-curran-dqvlc?file=/src/AntDFormChild.js https://codesandbox.io/s/vigilant-curran-dqvlc?file=/src/AntDFormChild.js

Example例子

const formLayout = {
  labelCol: { span: 8 },
  wrapperCol: { span: 7 }
};

const questionDefaultValues = {
  rjr01_q01: 2,
  rjr02_q01: 2
};

const AntDForm = () => {
  const [form] = Form.useForm();

  const handleResetForm = () => {
    form.resetFields();
    // now force onChange of child component to update
  };

  const handleFillForm = () => {
    form.setFieldsValue({ rjr01_q01: 1, rjr02_q01: 1 });
    // now force onChange of child component to update
  };

  return (
    <>
      <Button onClick={handleResetForm}>Reset Form</Button>
      <Button onClick={handleFillForm}>Fill Form</Button>
      <Form
        {...formLayout}
        form={form}
        initialValues={{ ...questionDefaultValues }}
      >
        <AntDFormChild form={form} />
      </Form>
    </>
  );
};

const questionQualifiedValues = {
  rjr01_q01: 1,
  rjr02_q01: 1
};

const AntDFormChild = ({ form }) => {
  const [isQualified, setIsQualified] = useState(false);
  const [questionFormValues, setQuestionFormValues] = useState({});

  useEffect(() => {
    if (shallowEqual(questionFormValues, questionQualifiedValues)) {
      setIsQualified(true);
    } else {
      setIsQualified(false);
    }
  }, [questionFormValues]);

  function shallowEqual(object1, object2) {
    const keys1 = Object.keys(object1);
    const keys2 = Object.keys(object2);
    if (keys1.length !== keys2.length) {
      return false;
    }
    for (let key of keys1) {
      if (object1[key] !== object2[key]) {
        return false;
      }
    }
    return true;
  }

  return (
    <>
      {isQualified && (
        <div style={{ color: "red" }}>You checked all answered with yes</div>
      )}
      <Form.Item name="rjr01_q01" label="Question 1">
        <Radio.Group
          onChange={(i) => {
            setQuestionFormValues((questionFormValues) => ({
              ...questionFormValues,
              rjr01_q01: i.target.value
            }));
          }}
        >
          <Radio value={1}>Yes</Radio>
          <Radio value={0}>No</Radio>
          <Radio value={2}>Unknown</Radio>
        </Radio.Group>
      </Form.Item>
      <Form.Item name="rjr02_q01" label="Question 2">
        <Radio.Group
          onChange={(i) => {
            setQuestionFormValues((questionFormValues) => ({
              ...questionFormValues,
              rjr02_q01: i.target.value
            }));
          }}
        >
          <Radio value={1}>Yes</Radio>
          <Radio value={0}>No</Radio>
          <Radio value={2}>Unknown</Radio>
        </Radio.Group>
      </Form.Item>
    </>
  );
};

Since AntD Form is uncontrolled, there is no way to trigger onChange event by calling resetFields , setFieldsValues .由于 AntD Form 不受控制,因此无法通过调用resetFieldssetFieldsValues来触发onChange事件。 I think your goal is to show the message depending on form values, and the best way to do is to use Form.Item , which can access form state.我认为您的目标是根据表单值显示消息,最好的方法是使用Form.Item ,它可以访问表单 state。

https://codesandbox.io/s/antd-form-item-based-on-other-item-ens59?file=/src/AntDFormChild.js https://codesandbox.io/s/antd-form-item-based-on-other-item-ens59?file=/src/AntDFormChild.js

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM