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
'programing' 카테고리의 다른 글
| 관계형 데이터베이스 대신 NoSQL 데이터베이스를 사용해야 하는 경우둘 다 같은 사이트에서 사용해도 될까요? (0) | 2023.04.05 |
|---|---|
| 정의 파일의 클래스 가져오기(*d.ts) (0) | 2023.04.05 |
| 로그에 WARN 메시지를 기록하지 않는 Spring @ExceptionHandler 메서드를 작성하려면 어떻게 해야 합니까? (0) | 2023.03.31 |
| JSON에 적합한 CLI 툴은 무엇입니까? (0) | 2023.03.31 |
| MVC 4 부트스트랩을 사용한 모달폼 편집 (0) | 2023.03.31 |