안녕하세요, 오늘은 가볍게 Yup+Formik을 사용할 때 유효성 검사에 대해 얘기해 보겠습니다.
오늘 겪었던 바보 같은 일을 회고하면서 Yup과 Formik에 대해서도 간단히 소개하겠습니다.
1. Yup
Dead simple Object schema validation
라고 소개합니다. 유효성 검사를 선언적으로 할 수 있게 해줍니다.
가장 상단에 있는 예시를 보면 형태가 모두 객체 형태인 것을 볼 수 있습니다. 심지어 if-else 기능에 해당하는 부분도 객체 형태로 사용이 가능합니다.
let userSchema = object({
name: string().required(),
age: number().required().positive().integer(),
email: string().email(),
website: string().url().nullable(),
createdOn: date().default(() => new Date()),
});
1depth의 객체의 원소값이라면 폼은 정말 간단하게 유효성 검사를 할 수 있습니다. 폼의 depth가 깊어질수록 복잡해지고 헷갈릴 수 있으니 Yup의 맥락에 대해 충분히 이해하고 작성하면 도움이 될 것 같습니다.
users: [{name: ‘Bob’, email: ‘test@domain.com}]
형태라면 아래와 같이 array().of
와 object().shape
로 감싸주어야 합니다.
users: Yup.array().of(
Yup.object().shape({
name: Yup.string().required("Name required"),
email: Yup.string()
.required("email required")
.email("Enter valid email")
})
)
2. Formik
Build forms in React, without the tears
라고 소개합니다. 프론트엔드에서 폼이 얼마나 복잡하게 그려지는지 알게 되는 문구인 것 같습니다.
Formik은 라이브러리 이름 그대로 Formik
라는 컴포넌트를 폼 상단에 감싸주고 값, 유효성검사, 폼 제출에 관련된 함수를 prop으로 넘겨주면 아래 Field
에서 자동으로 유효성검사와 값의 변경이 이루어집니다.
Formik
컴포넌트를 생성하면 FormikContext
가 생성되기 때문에 폼 내에서는 값을 자유롭게 사용할 수 있습니다.
Formik, Field
컴포넌트를 각각 useFormik
, useField
훅으로 대체 가능합니다. 하지만 훅을 사용할 경우는 훅을 호출한 컴포넌트에만 컨텍스트가 유지되므로 복잡한 폼에서는 컴포넌트 사용이 좋다고 느껴지네요.
<Formik initialValues={...} onSubmit={...} validateSchema={userSchema}>
<Form>(...)</Form>
</Formik>
3. 유효성 검사
Formik
에서 일반 유효성 검사 함수가 아닌 validateSchema
(Yup 스키마 형태)도 지원을 하고 있기 때문에 Yup으로 작성한 유효성 검사 스키마를 prop으로 넣으면 됩니다.
여기서 저의 헤매는 시나리오입니다. 😅 생각할수록 부끄럽네요..
- Formik의
initialValues
와는 별개로 배열을 만들어 빈 Input들을 랜더링했다.
// 배열 예시
const users = [{ name: "", email: "" }];
- 이 상태에서 유효한 값을 넣으면 잘 들어갔고, 최종 저장도 잘 되었다. → 문제점을 인지하지 못함
- 내가 원하는 유효성 검사는 빈 값을 처음부터 검사하기, 타입에 따라 특정 타입은 0보다 큰지 검사하는 것이었다.
- 처음부터 유효성검사를 하려면 빈 값을 focus → blur했을 때 유효성 검사를 해야 하지만 아무런 검사가 없었다. → 당연하다 검사할 값이 없으니까
- Yup 코드가 문제인가 싶어 계속 고치다가 상단 Formik 부분까지 도달하였다.. 설마..? 하고 고치니까 잘 동작했다.
전체 예시 오류 상황은 아래에 첨부하겠습니다. 주석된 부분이 잘 동작하는 코드입니다. 코드 예시는 인터넷에서 가져온 것입니다.
4. 마무리
컴포넌트와 유틸이 모두 분리되어 있어 발견을 빨리 못했던 것 같기도 합니다. 기능이 커서 분리해야 할 경우에는 어느 부분에 영향을 받는지 다양하게 살펴봐야겠습니다. 빠르게 수정하려다가 본질적인 문제를 보지 못하고 시간을 많이 쏟게 된 부분이 아쉽지만, 한 번 정리했으니 다음에는 이런 실수가 없었으면 좋겠습니다.
다음 글에서는 Npm에 라이브러리를 릴리즈하고 Contributor가 된 이야기를 작성해 보도록 하겠습니다.
읽어 주셔서 감사합니다!