programing

Formik의 setError 메서드를 올바르게 사용하는 방법(리액트 라이브러리)

goodjava 2023. 3. 31. 22:24

Formik의 setError 메서드를 올바르게 사용하는 방법(리액트 라이브러리)

백엔드와 통신하는 React를 사용하고 있습니다.폼 라이브러리(Form Library)를 제대로 구현하기 위해 노력하고 있습니다.

주요 질문:Formik의 setError 메서드를 올바르게 사용하려면 어떻게 해야 합니까?

클라이언트측의 검증 에러는 올바르게 표시되지만, 현재는 백엔드 검증 에러를 설정/표시하려고 하고 있습니다.백엔드 검증 에러는 상태 코드 400의 응답으로 반환됩니다.

사용하려는 메서드의 문서에 대한 링크

아래 코드에서 handle400Error라는 이름의 메서드를 사용하고 있습니다.

My React(및 Formik) 코드:

import React, { Component } from "react";
import axios from "axios";
import { Formik } from "formik";
import * as Yup from "yup";
import styled from "styled-components";
import FormError from "../formError";

const Label = styled.label``;

class LoginForm extends Component {
  initialValues = {
    password: "",
    username: ""
  };

  getErrorsFromValidationError = validationError => {
    const FIRST_ERROR = 0;
    return validationError.inner.reduce((errors, error) => {
      return {
        ...errors,
        [error.path]: error.errors[FIRST_ERROR]
      };
    }, {});
  };

  getValidationSchema = values => {
    return Yup.object().shape({
      password: Yup.string()
        .min(6, "Password must be at least 6 characters long")
        .required("Password is required!"),
      username: Yup.string()
        .min(5, "Username must be at least 5 characters long")
        .max(40, "Username can not be longer than 40 characters")
        .required("Username is required")
    });
  };

  handleSubmit = async (values, { setErrors }) => {
    console.log("handleSubmit");

    try {
      const response = await axios.post(
        "http://127.0.0.1:8000/rest-auth/login/",
        values
      );
      const loginToken = response.data["key"];
      this.handleLoginSuccess(loginToken);
    } catch (exception) {
      // Expected: 400 status code
      if (exception.response && exception.response.status === 400) {
        // Display server validation errors
        this.handle400Error(exception.response.data, setErrors);
      }
      console.log("exception", exception);
      console.log("exception.response", exception.response);
    }
  };

  handle400Error = (backendErrors, setErrors) => {
    let errors = {};
    for (let key in backendErrors) {
      errors[key] = backendErrors[key][0]; // for now only take the first error of the array
    }
    console.log("errors object", errors);
    setErrors({ errors });
  };

  handleUnexpectedError = () => {};

  handleLoginSuccess = loginToken => {
    console.log("handleLoginSuccess");
    this.props.setGreeneryAppState({
      loginToken: loginToken
    });
    this.props.history.replace(`/${this.props.locale}/`);
  };

  validate = values => {
    const validationSchema = this.getValidationSchema(values);
    try {
      validationSchema.validateSync(values, { abortEarly: false });
      return {};
    } catch (error) {
      return this.getErrorsFromValidationError(error);
    }
  };

  render() {
    return (
      <React.Fragment>
        <h1>Login</h1>
        <Formik
          initialValues={this.initialValues}
          validate={this.validate}
          validationSchema={this.validationSchema}
          onSubmit={this.handleSubmit}
          render={({
            errors,
            touched,
            values,
            handleBlur,
            handleChange,
            handleSubmit
          }) => (
            <form onSubmit={handleSubmit}>
              {errors.non_field_errors && (
                <formError>{errors.non_field_errors}</formError>
              )}
              <Label>Username</Label>
              <input
                onChange={handleChange}
                onBlur={handleBlur}
                value={values.username}
                type="text"
                name="username"
                placeholder="Enter username"
              />
              {touched.username &&
                errors.username && <FormError>{errors.username}</FormError>}
              <Label>Password</Label>
              <input
                onChange={handleChange}
                onBlur={handleBlur}
                value={values.password}
                type="password"
                name="password"
                placeholder="Enter password"
              />
              {touched.password &&
                errors.password && <FormError>{errors.password}</FormError>}
              <button type="submit">Log in</button>
            </form>
          )}
        />
      </React.Fragment>
    );
  }

여기 포믹 작가...

setErrorv0.8.0에서 더 이상 사용되지 않고 로 이름이 변경되었습니다.setStatus를 사용할 수 있습니다.setErrors(errors)또는setStatus(whateverYouWant)당신의 안에서handleSubmit다음과 같은 기능을 통해 원하는 동작을 얻을 수 있습니다.

handleSubmit = async (values, { setErrors, resetForm }) => {
   try {
     // attempt API call
   } catch(e) {
     setErrors(transformMyApiErrors(e))
     // or 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는 다음 폼의 제출을 막는 데 영향을 미치지 않습니다.Formik은 검증에 실패한 경우에만 제출 프로세스를 중단합니다.

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

나는 방금 내 문제를 해결했다.

사용할 필요가 있었습니다.

setErrors( errors )

다음 대신:

setErrors({ errors })

이 상황에 대처하는 또 다른 방법은 특정 키를 할당하는 것입니다.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>

스키마도 잊지 말고...

const LoginSchema = Yup.object().shape({
  login: Yup.string()
    .min(4, 'Too Short!')
    .max(70, 'Too Long!')
    .required('Login is required'),
});

api에러 메세지는, Formik 의 다음의 검증 콜까지 표시됩니다(즉, 유저가 무언가를 수정하고 있습니다).근데...status메시지는 클리어될 때까지 유지됩니다(타이머 또는 페이드 사용).

이게 네가 보고 있는 거야

setErrors({ username: 'This is a dummy procedure error' });
<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>
  )}
/>

언급URL : https://stackoverflow.com/questions/52986962/how-to-properly-use-formiks-seterror-method-react-library