Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/409.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何正确使用Formik';什么是setError方法?(反应库)_Javascript_Reactjs_Formik - Fatal编程技术网

Javascript 如何正确使用Formik';什么是setError方法?(反应库)

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

我正在使用React与后端进行通信。现在正在尝试正确地实现Formik(表单库)

主要问题: 如何正确使用Formik的setError方法?

客户端验证错误正确显示,但现在我正在尝试设置/显示后端验证错误,返回的响应状态代码为400

我尝试使用的方法的文档

我在下面代码中名为handle400Error的方法中使用此方法

我的React(和Formik)代码:

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

IMHO
setStatus
在这里实际上非常理想,因为它会将错误消息放在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实现(后端和前端错误)的人有很大帮助。is
setErrors
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