Javascript 如何正确使用Formik';什么是setError方法?(反应库)
我正在使用React与后端进行通信。现在正在尝试正确地实现Formik(表单库) 主要问题: 如何正确使用Formik的setError方法? 客户端验证错误正确显示,但现在我正在尝试设置/显示后端验证错误,返回的响应状态代码为400 我尝试使用的方法的文档 我在下面代码中名为handle400Error的方法中使用此方法 我的React(和Formik)代码:Javascript 如何正确使用Formik';什么是setError方法?(反应库),javascript,reactjs,formik,Javascript,Reactjs,Formik,我正在使用React与后端进行通信。现在正在尝试正确地实现Formik(表单库) 主要问题: 如何正确使用Formik的setError方法? 客户端验证错误正确显示,但现在我正在尝试设置/显示后端验证错误,返回的响应状态代码为400 我尝试使用的方法的文档 我在下面代码中名为handle400Error的方法中使用此方法 我的React(和Formik)代码: import React,{Component}来自“React”; 从“axios”导入axios; 从“Formik”导入{For
import React,{Component}来自“React”;
从“axios”导入axios;
从“Formik”导入{Formik};
从“Yup”导入*作为Yup;
从“样式化组件”导入样式化;
从“./FormError”导入FormError;
const Label=styled.Label`;
类LoginForm扩展组件{
初始值={
密码:“”,
用户名:“
};
getErrorsFromValidationError=validationError=>{
const FIRST_ERROR=0;
返回validationError.Internal.reduce((错误,错误)=>{
返回{
…错误,
[error.path]:error.errors[第一个错误]
};
}, {});
};
getValidationSchema=值=>{
返回Yup.object().shape({
密码:Yup.string()
.min(6,“密码长度必须至少为6个字符”)
.required(“需要密码!”),
用户名:Yup.string()
.min(5,“用户名长度必须至少为5个字符”)
.max(40,“用户名不能超过40个字符”)
.required(“需要用户名”)
});
};
handleSubmit=async(值,{setErrors})=>{
console.log(“handleSubmit”);
试一试{
const response=等待axios.post(
"http://127.0.0.1:8000/rest-auth/login/“,
价值观
);
const loginToken=response.data[“key”];
这是HandleLoginsAccess(loginToken);
}捕获(例外){
//预期:400状态代码
if(exception.response&&exception.response.status==400){
//显示服务器验证错误
this.handle400Error(exception.response.data,setErrors);
}
console.log(“异常”,异常);
log(“exception.response”,exception.response);
}
};
handle400Error=(backendErrors,setErrors)=>{
让错误={};
用于(让输入靠背箭头){
errors[key]=backendErrors[key][0];//现在只取数组的第一个错误
}
日志(“错误对象”,错误);
setErrors({errors});
};
handleUnexpectedError=()=>{};
HandleLoginsAccess=loginToken=>{
console.log(“handleLoginsAccess”);
this.props.setGreeneryAppState({
罗金托肯:罗金托肯
});
this.props.history.replace(`/${this.props.locale}/`);
};
验证=值=>{
const validationSchema=this.getValidationSchema(值);
试一试{
validationSchema.validateSync(值,{abortEarly:false});
返回{};
}捕获(错误){
返回此.getErrorsFromValidationError(错误);
}
};
render(){
返回(
登录
(
{errors.non_field_errors&&(
{errors.non_field_errors}
)}
用户名
{moved.username&&
errors.username&&{errors.username}
密码
{密码&&
errors.password&&{errors.password}
登录
)}
/>
);
}
我刚刚解决了自己的问题
我需要使用:
setErrors( errors )
而不是:
setErrors({ errors })
福米克的作者在这里
setError
被重命名为setStatus
。您可以在handleSubmit
函数中使用setErrors(errors)
或setStatus(whateverYouWant)
来获得您想要的行为,如下所示:
handleSubmit=async(值,{setErrors,resetForm})=>{
试一试{
//尝试API调用
}捕获(e){
setErrors(TransformMyAPIRRORS(e))
//或setStatus(transformMyApiErrors(e))
}
}
使用setStatus
与setErrors
有什么区别?
如果您使用setErrors
,您的错误将被Formik的下一个validate
或validationSchema
调用清除,该调用可由用户键入(更改事件)或模糊输入(模糊事件)触发。注意:这假设您没有手动将validateOnChange
和validateOnBlur
道具设置为false
(默认情况下它们是true
)
IMHOsetStatus
在这里实际上非常理想,因为它会将错误消息放在Formik状态的一个单独部分上。然后,您可以像这样决定如何/何时向最终用户显示此消息
// status can be whatever you want
{!!status && <FormError>{status}</FormError>}
// or mix it up, maybe transform status to mimic errors shape and then ...
{touched.email && (!!errors.email && <FormError>{errors.email}</FormError>) || (!!status && <FormError>{status.email}</FormError>) }
//状态可以是任何您想要的
{!!状态&&{status}
//或者把它混在一起,也许转换状态来模拟错误的形状,然后。。。
{toucted.email&(!!errors.email&&{errors.email})| |(!!status&&{status.email})}
请注意,
状态的存在或值
不会影响下一次表单提交。Formik仅中止。处理此情况的另一种方法是为您的api
错误分配一个特定键,并使用setStatus
获取状态消息
__handleSubmit = (values, {setStatus, setErrors}) => {
return this.props.onSubmit(values)
.then(() => {
setStatus("User was updated successfully.");
})
.catch((err) => {
setErrors({api: _.get(err, ["message"])});
});
}
然后,任何验证错误都会显示在字段中,任何api错误都会显示在底部:
<Formik
validationSchema={LoginSchema}
initialValues={{login: ""}}
onSubmit={this.__handleSubmit}
>
{({isSubmitting, status, errors, values, setFieldValue}) => (
<Form className={classNames("form")}>
<FormGroup>
<InputGroup>
<InputGroup.Text>
<FontAwesomeIcon icon={faUser} fixedWidth />
</InputGroup.Text>
<Field
name="login"
type={"text"}
placeholder="Login"
className="form-control"
/>
</InputGroup>
<ErrorMessage name="login" />
</FormGroup>
<Button type="submit" variant="primary" disabled={isSubmitting}>
Submit
</Button>
{errors && _.has(errors, ["api"]) && <div className="text-danger">{_.get(errors, ["api"])}</div>}
{status && <div className="text-success">{status}</div>}
</Form>
)}
</Formik>
api
错误消息将一直显示,直到Formik下一次验证调用(即用户正在修复某些东西)为止。但是状态
消息将一直保留,直到您清除它(使用计时器或淡入淡出)。{
//初始化错误状态{
//设置错误状态您的代码块对于在Formik中查找setError实现(后端和前端错误)的人有很大帮助。issetErrors
still
<Formik
validationSchema={LoginSchema}
initialValues={{login: ""}}
onSubmit={this.__handleSubmit}
>
{({isSubmitting, status, errors, values, setFieldValue}) => (
<Form className={classNames("form")}>
<FormGroup>
<InputGroup>
<InputGroup.Text>
<FontAwesomeIcon icon={faUser} fixedWidth />
</InputGroup.Text>
<Field
name="login"
type={"text"}
placeholder="Login"
className="form-control"
/>
</InputGroup>
<ErrorMessage name="login" />
</FormGroup>
<Button type="submit" variant="primary" disabled={isSubmitting}>
Submit
</Button>
{errors && _.has(errors, ["api"]) && <div className="text-danger">{_.get(errors, ["api"])}</div>}
{status && <div className="text-success">{status}</div>}
</Form>
)}
</Formik>
const LoginSchema = Yup.object().shape({
login: Yup.string()
.min(4, 'Too Short!')
.max(70, 'Too Long!')
.required('Login is required'),
});
<Formik
validationSchema={schema}
initialValues={{ email: '', pswrd: '' }}
onSubmit={(values, actions) => {
// initialise error status <---- 1
actions.setStatus(undefined);
setTimeout(() => {
// setting error status <---- 2
actions.setStatus({
email: 'This is email already exists.',
pswrd: 'This is password is incorrect',
});
}, 500);
}}
// destructuring status <---- 3
render={({ handleSubmit, handleChange, handleBlur, values, errors, status }) => (
<form onSubmit={handleSubmit}>
<input
type="text"
name="email"
value={values['email']}
onChange={handleChange}
onBlur={handleBlur}
/>
<input
type="text"
name="pswrd"
value={values['pswrd']}
onChange={handleChange}
onBlur={handleBlur}
/>
<button type="submit">Submit</button>
// using error status <---- 4
{status && status.email ? (
<div>API Error: {status.email}</div>
) : (
errors.email && <div>Validation Error: {errors.email}</div>
)}
{status && status.pswrd ? (
<div>API Error: {status.pswrd}</div>
) : (
errors.pswrd && <div>Validation Error: {errors.pswrd}</div>
)}
</form>
)}
/>
const formik = useFormik({
initialValues:{
email:"",password:"",username:""
},
validationSchema:validation_schema,
onSubmit:(values) => {
const {email,password,username} = values
// ......
}
});
formik.setErrors({email:"Is already taken"}) // error message for email field