有效字段更改后,Formik 调度 Redux 操作
Formik dispatch Redux action after valid field change
我构建了这个使用 Formik 表单的沙盒 React 应用程序。
如果电子邮件字段验证触发且有效,我想调度 Redux 操作。
我想分派操作以从用户电子邮件中进行一些查找。此操作将更新 redux 状态并填充我表单上的其他字段。
因此,如果电子邮件字段有效,则会发生此调度。其他字段可能无效,我还没有提交表单。
我该怎么做?我找不到关于此的任何文档!
https://codesandbox.io/s/x32yoo242q
谢谢!
您可以创建一个可重复使用的自定义 component
调用对 input
更新的辅助操作。在这种情况下,如果输入有效且具有值,它将调度 action
(redux 操作),如果无效,and/or 可选择调度辅助操作。
更新:利用componentDidUpdate
。它不那么冗长,并且需要较少的手动字段级处理。此外,你还应该 debounce
避免大量 redux 操作触发的功能。
工作示例(电子邮件):
工作示例 (Material UI Select):
components/Input(自定义组件--componentDidUpdate
控制是否调用validateField
)
import React, { Fragment, PureComponent } from "react";
class Input extends PureComponent {
componentDidUpdate = prevProps => {
const { errors, value } = this.props;
if (errors !== prevProps.errors || value !== prevProps.value) {
this.props.validateField({ errors, value });
}
};
render = () => {
const { errors, label, name, touched, validateField, ...rest } = this.props;
return (
<Fragment>
<label htmlFor={name} style={{ display: "block" }}>
{label}
</label>
<input {...rest} name={name} />
{errors && touched && (
<div style={{ color: "red", marginTop: ".5rem" }}>{errors}</div>
)}
</Fragment>
);
};
}
export default Input;
containers/Form(validateField
控制 redux 动作)
import debounce from "lodash/debounce";
import React from "react";
import { withFormik } from "formik";
import Input from "../../components/Input";
import DisplayFormikState from "../../components/DisplayFormState";
import { resetMessage, setMessage } from "../../actions/message";
import store from "../../store";
import * as Yup from "yup";
const formikEnhancer = withFormik({
validationSchema: Yup.object().shape({
email: Yup.string()
.email("Invalid email address")
.required("Email is required!")
}),
mapPropsToValues: props => ({
email: ""
}),
handleSubmit: (values, { setSubmitting }) => {
const payload = {
...values
};
setTimeout(() => {
alert(JSON.stringify(payload, null, 2));
setSubmitting(false);
}, 1000);
},
displayName: "MyForm"
});
const handleFormReset = handleReset => {
store.dispatch(resetMessage());
handleReset();
};
const validateField = debounce(
({ errors, value }) =>
!errors && value
? store.dispatch(setMessage())
: store.dispatch(resetMessage()),
500
);
const MyForm = props => {
const {
values,
touched,
dirty,
errors,
handleBlur,
handleChange,
handleReset,
handleSubmit,
isSubmitting
} = props;
return (
<form onSubmit={handleSubmit}>
<Input
name="email"
label="Email"
type="email"
placeholder="Enter an email address."
errors={errors.email}
value={values.email}
touched={touched.email}
onChange={handleChange}
onBlur={handleBlur}
validateField={validateField}
/>
<button
type="button"
className="outline"
onClick={() => handleFormReset(handleReset)}
disabled={!dirty || isSubmitting}
>
Reset
</button>
<button type="submit" disabled={isSubmitting}>
Submit
</button>
<DisplayFormikState {...props} />
</form>
);
};
export default formikEnhancer(MyForm);
实现您想要的效果的最简单直接的方法是使用电子邮件输入的 onBlur
处理程序。您可以通过执行以下操作来扩展默认处理程序:
<input
id="email"
placeholder="Enter your email"
type="email"
value={values.email}
onChange={handleChange}
onBlur={e => {
handleBlur(e);
if (!errors.email) {
console.log("dispatch: ", e.currentTarget.value);
}
}}
/>
通过首先调用 Formik 的 handleBlur
,您可以保留默认的验证行为,同时随后添加您自己的验证行为。您的表单正在验证 onChange
以及 onBlur
所以 errors.email
应该始终准确表示电子邮件输入的有效性,如果电子邮件在模糊状态下有效,我们可以使用它来发送(在我的示例中,我只是将一些内容记录到控制台以进行说明)。查看 沙盒 以查看它的实际效果:
我构建了这个使用 Formik 表单的沙盒 React 应用程序。
如果电子邮件字段验证触发且有效,我想调度 Redux 操作。 我想分派操作以从用户电子邮件中进行一些查找。此操作将更新 redux 状态并填充我表单上的其他字段。
因此,如果电子邮件字段有效,则会发生此调度。其他字段可能无效,我还没有提交表单。
我该怎么做?我找不到关于此的任何文档!
https://codesandbox.io/s/x32yoo242q
谢谢!
您可以创建一个可重复使用的自定义 component
调用对 input
更新的辅助操作。在这种情况下,如果输入有效且具有值,它将调度 action
(redux 操作),如果无效,and/or 可选择调度辅助操作。
更新:利用componentDidUpdate
。它不那么冗长,并且需要较少的手动字段级处理。此外,你还应该 debounce
避免大量 redux 操作触发的功能。
工作示例(电子邮件):
工作示例 (Material UI Select):
components/Input(自定义组件--componentDidUpdate
控制是否调用validateField
)
import React, { Fragment, PureComponent } from "react";
class Input extends PureComponent {
componentDidUpdate = prevProps => {
const { errors, value } = this.props;
if (errors !== prevProps.errors || value !== prevProps.value) {
this.props.validateField({ errors, value });
}
};
render = () => {
const { errors, label, name, touched, validateField, ...rest } = this.props;
return (
<Fragment>
<label htmlFor={name} style={{ display: "block" }}>
{label}
</label>
<input {...rest} name={name} />
{errors && touched && (
<div style={{ color: "red", marginTop: ".5rem" }}>{errors}</div>
)}
</Fragment>
);
};
}
export default Input;
containers/Form(validateField
控制 redux 动作)
import debounce from "lodash/debounce";
import React from "react";
import { withFormik } from "formik";
import Input from "../../components/Input";
import DisplayFormikState from "../../components/DisplayFormState";
import { resetMessage, setMessage } from "../../actions/message";
import store from "../../store";
import * as Yup from "yup";
const formikEnhancer = withFormik({
validationSchema: Yup.object().shape({
email: Yup.string()
.email("Invalid email address")
.required("Email is required!")
}),
mapPropsToValues: props => ({
email: ""
}),
handleSubmit: (values, { setSubmitting }) => {
const payload = {
...values
};
setTimeout(() => {
alert(JSON.stringify(payload, null, 2));
setSubmitting(false);
}, 1000);
},
displayName: "MyForm"
});
const handleFormReset = handleReset => {
store.dispatch(resetMessage());
handleReset();
};
const validateField = debounce(
({ errors, value }) =>
!errors && value
? store.dispatch(setMessage())
: store.dispatch(resetMessage()),
500
);
const MyForm = props => {
const {
values,
touched,
dirty,
errors,
handleBlur,
handleChange,
handleReset,
handleSubmit,
isSubmitting
} = props;
return (
<form onSubmit={handleSubmit}>
<Input
name="email"
label="Email"
type="email"
placeholder="Enter an email address."
errors={errors.email}
value={values.email}
touched={touched.email}
onChange={handleChange}
onBlur={handleBlur}
validateField={validateField}
/>
<button
type="button"
className="outline"
onClick={() => handleFormReset(handleReset)}
disabled={!dirty || isSubmitting}
>
Reset
</button>
<button type="submit" disabled={isSubmitting}>
Submit
</button>
<DisplayFormikState {...props} />
</form>
);
};
export default formikEnhancer(MyForm);
实现您想要的效果的最简单直接的方法是使用电子邮件输入的 onBlur
处理程序。您可以通过执行以下操作来扩展默认处理程序:
<input
id="email"
placeholder="Enter your email"
type="email"
value={values.email}
onChange={handleChange}
onBlur={e => {
handleBlur(e);
if (!errors.email) {
console.log("dispatch: ", e.currentTarget.value);
}
}}
/>
通过首先调用 Formik 的 handleBlur
,您可以保留默认的验证行为,同时随后添加您自己的验证行为。您的表单正在验证 onChange
以及 onBlur
所以 errors.email
应该始终准确表示电子邮件输入的有效性,如果电子邮件在模糊状态下有效,我们可以使用它来发送(在我的示例中,我只是将一些内容记录到控制台以进行说明)。查看 沙盒 以查看它的实际效果: