尽管有条件渲染,React 表单可以提交两次
React form can be submitted twice despite conditional render
我有一个与 Redux 耦合的 React 应用程序。有一个组件呈现表单包装器(Formik 的自定义实现),而表单输入本身由子组件呈现。
(不是确切的代码,但明白了要点。)
...
render() {
const {
config,
updateContactDetails,
errorMessages,
contactDetails,
previousFormValues,
isUpdating,
} = this.props;
const { apiBaseUrl, fetchTimeout, globalId } = config;
const initialValues = previousFormValues || getInitialContactDetailsValues(contactDetails);
if (isUpdating) return <Spinner />;
return (
<Form
initialValues={initialValues}
validate={(values) => validate(values, errorMessages)}
onSubmit={(values) => {
updateContactDetails(apiBaseUrl, globalId, values, fetchTimeout); // dispatch action
}}
>
<ContactDetailsForm content={content} />
</Form>
);
}
...
当你点击ContactDetailsForm
中的提交按钮时,Redux store中isUpdating
的值被设置为true。正如您在上面看到的,这导致表单被一个微调器组件替换。但是,以某种方式可以通过单击按钮两次来提交表单两次。
怎么会这样?在用微调器替换表单之前是否会重新渲染?我知道我可以通过将 isUpdating
传递给 ContactDetailsForm
并使用它来禁用按钮来解决问题,但我仍然想阐明原因。
编辑
reducer 看起来像这样,以防有帮助:
case UPDATE_CONTACT_DETAILS_START: {
return {
...state,
errorUpdatingContactMethods: {},
hasUpdatedContactDetails: false,
isUpdating: true,
contactDetailsValues: action.values,
};
}
您应该根据 isUpdating
属性在按钮上设置 disabled
属性。这可能只是一个竞争条件。
我有一个与 Redux 耦合的 React 应用程序。有一个组件呈现表单包装器(Formik 的自定义实现),而表单输入本身由子组件呈现。
(不是确切的代码,但明白了要点。)
...
render() {
const {
config,
updateContactDetails,
errorMessages,
contactDetails,
previousFormValues,
isUpdating,
} = this.props;
const { apiBaseUrl, fetchTimeout, globalId } = config;
const initialValues = previousFormValues || getInitialContactDetailsValues(contactDetails);
if (isUpdating) return <Spinner />;
return (
<Form
initialValues={initialValues}
validate={(values) => validate(values, errorMessages)}
onSubmit={(values) => {
updateContactDetails(apiBaseUrl, globalId, values, fetchTimeout); // dispatch action
}}
>
<ContactDetailsForm content={content} />
</Form>
);
}
...
当你点击ContactDetailsForm
中的提交按钮时,Redux store中isUpdating
的值被设置为true。正如您在上面看到的,这导致表单被一个微调器组件替换。但是,以某种方式可以通过单击按钮两次来提交表单两次。
怎么会这样?在用微调器替换表单之前是否会重新渲染?我知道我可以通过将 isUpdating
传递给 ContactDetailsForm
并使用它来禁用按钮来解决问题,但我仍然想阐明原因。
编辑
reducer 看起来像这样,以防有帮助:
case UPDATE_CONTACT_DETAILS_START: {
return {
...state,
errorUpdatingContactMethods: {},
hasUpdatedContactDetails: false,
isUpdating: true,
contactDetailsValues: action.values,
};
}
您应该根据 isUpdating
属性在按钮上设置 disabled
属性。这可能只是一个竞争条件。