[英]Ant Design React Form fire onChange event on form.resetFields()
I'm having an Ant Design <Form>
component with multiple <Form.Items>
.我有一个带有多个
<Form.Items>
的 Ant Design <Form>
组件。 One of them is a <Select>
which is dependents on multiple other <Form.Item>
states to change the <Options>
styling depending on the combination of chosen values in the other <Form.Items>
.其中之一是
<Select>
,它依赖于多个其他<Form.Item>
状态来更改<Options>
样式,具体取决于其他<Form.Items>
中所选值的组合。 I'm working with an extra useState object ( activeQuestions
) to make more complex combinations easier to handle.我正在使用额外的 useState object (
activeQuestions
) 以使更复杂的组合更易于处理。 My issue is when the form is being reset by form.resetFormFields()
or set by form.setFieldsValue()
it won't call my used onChange events as antd form is an uncontrolled form.我的问题是当表单由
form.resetFormFields()
重置或由form.setFieldsValue()
设置时,它不会调用我使用的 onChange 事件,因为 antd 表单是不受控制的表单。 So I'm not sure how to approach this.所以我不确定如何解决这个问题。 There is shouldUpdate on
<Form.Items>
but I'm not sure how and if this is the right approach for this goal. <Form.Items>
上有 shouldUpdate 但我不确定这是如何以及是否是实现此目标的正确方法。
So in the simplified example sandbox, I created, when changing all the the <Radio>
to Yes it fires the onChange event which is validated, and then greying out some of the selection options.因此,在我创建的简化示例沙箱中,当将所有
<Radio>
更改为 Yes 时,它会触发经过验证的 onChange 事件,然后将一些选择选项变灰。
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/antd-form-item-based-on-other-item-forked-zofnj?file=/src/AntDFormChild.js https://codesandbox.io/s/antd-form-item-based-on-other-item-forked-zofnj?file=/src/AntDFormChild.js
What I've tried (this causes an infinite loop)我尝试过的(这会导致无限循环)
<Form.Item
noStyle
shouldUpdate={(prevValues, currentValues) => {
console.log(prevValues.rjr01_q01, currentValues.rjr01_q01);
return (
prevValues.rjr01_q01 !== currentValues.rjr01_q01 &&
prevValues.rjr02_q01 !== currentValues.rjr02_q01
);
}}
>
{({ getFieldValue }) => {
setSelections((selections) => ({
rjr01_q01: getFieldValue("rjr01_q01"),
rjr02_q01: getFieldValue("rjr02_q01")
}));
return null;
}}
</Form.Item>
Example例子
import React, { useState, useEffect } from "react";
import { Descriptions, Form, Radio, Select, Typography } from "antd";
const { Text } = Typography;
const { Option } = Select;
const questionsData = {
rjr01_q01: { title: "Question 1", description: "Question 1 description" },
rjr02_q01: { title: "Question 2", description: "Question 2 description" }
};
const AntDFormChild = ({ form }) => {
const [selections, setSelections] = useState({
rjr01_q01: null,
rjr02_q01: null
});
const [activeQuestions, setActiveQuestions] = useState([]);
useEffect(() => {
console.log("selections state update", selections);
// if question 1 is yes
if (selections.rjr01_q01 === 1 && !activeQuestions.includes("rjr01_q01")) {
setActiveQuestions((activeQuestions) => [
...activeQuestions,
"rjr01_q01"
]);
}
// if question 1 is not yes
if (selections.rjr01_q01 !== 1 && activeQuestions.includes("rjr01_q01")) {
setActiveQuestions((activeQuestions) => [
...activeQuestions.filter((i) => i !== "rjr01_q01")
]);
}
// if question 2 is yes
if (selections.rjr02_q01 === 1 && !activeQuestions.includes("rjr02_q01")) {
setActiveQuestions((activeQuestions) => [
...activeQuestions,
"rjr02_q01"
]);
}
// if question 2 is not yes
if (selections.rjr02_q01 !== 1 && activeQuestions.includes("rjr02_q01")) {
setActiveQuestions((activeQuestions) => [
...activeQuestions.filter((i) => i !== "rjr02_q01")
]);
}
}, [selections]);
useEffect(() => {
console.log("activeQuestions state update", activeQuestions);
}, [activeQuestions]);
return (
<>
<Form.Item
noStyle
shouldUpdate={(prevValues, currentValues) => {
console.log(prevValues.rjr01_q01, currentValues.rjr01_q01);
return (
prevValues.rjr01_q01 !== currentValues.rjr01_q01 &&
prevValues.rjr02_q01 !== currentValues.rjr02_q01
);
}}
>
{({ getFieldValue }) =>
getFieldValue("rjr01_q01") === 1 &&
getFieldValue("rjr02_q01") === 1 ? (
<div style={{ color: "red" }}>
You checked all answered with yes
</div>
) : null
}
</Form.Item>
<Form.Item name="rjr01_q01" label="Question 1">
<Radio.Group
onChange={(i) => {
setSelections((selections) => ({
...selections,
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) => {
setSelections((selections) => ({
...selections,
rjr02_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="availableQuestions" label="Available Questions">
<Select allowClear style={{ width: 250 }}>
{Object.keys(questionsData).map((key, index) => (
<Option key={key} value={key}>
<Text
style={{
color: activeQuestions.includes(key) && "lightgrey"
}}
>
{questionsData[key].title}
</Text>
</Option>
))}
</Select>
</Form.Item>
</>
);
};
export default AntDFormChild;
You can lift your activeQuestions
state to the AntDForm
component and reset it together with the form:您可以将您的
activeQuestions
state 提升到AntDForm
组件并将其与表单一起重置:
const AntDForm = () => {
const [form] = Form.useForm();
const [activeQuestions, setActiveQuestions] = useState([]);
const handleResetForm = () => {
form.resetFields();
// now force onChange of child component to update
// Reset active questions
setActiveQuestions([]);
};
...
Then pass it to AntDFormChild
:然后将其传递给
AntDFormChild
:
<AntDFormChild
form={form}
activeQuestions={activeQuestions}
setActiveQuestions={setActiveQuestions}
/>
</Form>
And in <AntDFormChild>
make them props instead of its own state:并在
<AntDFormChild>
中使它们成为道具而不是它自己的 state:
const AntDFormChild = ({ form, activeQuestions, setActiveQuestions }) => {
Here's a sandbox link showing how it works.这是一个沙盒链接,展示了它的工作原理。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.