front-end 하면 빠질 수 없는 것이 Form이다.
하나하나 만들어서 관리하려니 코드도 길어지고 너무 힘들어서 라이브러리를 통해 관리해보려고 찾아봤다.
대표적인 라이브러리로 Formik과 React-hook-form이 있다.
이번에는 form라이브러리인 Formik과 유효성 검사 라이브러리 Yup을 사용해보려 한다.
제일 처음 formik과 yup을 설치하자
npm i formik
npm i yup
form에 사용 할 상태의 초기 값을 initialValues을 통해서 설정한다.
const formik = useFormik({
initialValues: {
firstName: "",
lastName: "",
channel: "",
},
});
초기 값을 사용 할 곳에서 value의 속성 값으로 초기 값을 연결해준다.
<label htmlFor="lastName">성</label>
<input
type="text"
id="lastName"
name="lastName"
value={formik.values.lastName}
/>
<label htmlFor="lastName">이름</label>
<input
type="text"
id="firstName"
name="firstName"
value={formik.values.firstName}
/>
input 값이 변경 될 때 사용하는 onChange에 formik의 handleChange를 연결한다.
여기서 handleChange를 사용하면 values [key]의 값이 업데이트된다. name 속성이 없으면 id 속성을 찾는다.
<label htmlFor="lastName">성</label>
<input
type="text"
id="lastName"
name="lastName"
value={formik.values.lastName}
onChange={formik.handleChange}
/>
<label htmlFor="lastName">이름</label>
<input
type="text"
id="firstName"
name="firstName"
value={formik.values.firstName}
onChange={formik.handleChange}
/>
폼 전송 이벤트 리스너 연결은 form태그의 onSubmit에 연결해준다.
<form onSubmit={formik.handleSubmit}>
<div>
<label htmlFor="lastName">성</label>
<input
type="text"
id="lastName"
name="lastName"
value={formik.values.lastName}
onChange={formik.handleChange}
/>
</div>
<div>
<label htmlFor="firstName">이름</label>
<input
type="text"
id="firstName"
name="firstName"
value={formik.values.firstName}
onChange={formik.handleChange}
/>
</div>
<button type="submit">전송</button>
</form>
물론 submit에 사용하는 함수도 초기값과 함께 작성해준다.
const formik = useFormik({
initialValues: {
firstName: "",
lastName: "",
channel: "",
},
onSubmit: (values) => {
console.log(values);
},
});
입력한 값의 유효성 검사를 진행할 수 있다.
먼저 사용자 정의 유효성 검사 함수를 생성하고 validate로 useFormik() hook에 연결한다.
useFomik()에 전달한 onSubmit 함수는 오류가 없는 경우에만 실행된다. (유효성 검사 함수가 {}를 반환하는 경우)
const validate = (values) => {
const errors = {};
if (!values.firstName) {
errors.name = "성 입력은 필수입니다.";
} else if (values.firstName.length < 2) {
errors.name = "성은 최대 2글자 입니다.";
}
if (!values.lastName) {
errors.name = "이름 입력은 필수입니다.";
}
if (!values.email) {
errors.email = "이메일 입력은 필수입니다.";
} else if (!/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(values.email)) {
errors.email =
"이메일 입력 형식이 올바르지 않습니다. 확인 후, 다시 입력하세요.";
}
return errors;
};
const formik = useFormik({
initialValues: {
firstName: "",
lastName: "",
channel: "",
},
onSubmit: (values) => {
console.log(values);
},
validate
});
이제 연결한 validate를 조건에 따라 표시해보자
<label htmlFor="lastName">성</label>
<input
type="text"
id="lastName"
name="lastName"
value={formik.values.lastName}
onChange={formik.handleChange}
/>
{formik.errors.lastName && <span role="alert">{formik.errors.lastName}</span>}
이제 콘솔창을 통해서 errors를 확인해보자
조건을 만족하지 못하면 errors [key] : value 값으로 객체에 생성될 것이고 모든 조건이 만족했다면 {} 빈객체를 반환할 것이다.
console.log(formik.errors)
validate를 이용하다보면 첫 입력부터 에러를 발생시킨다.
이러한 방법은 사용자에게 안좋은 경험을 만들어 주기 때문에 formik.touched를 사용해서 한 번이라도 입력한 후에 error를 발생시켜준다.
<label htmlFor="lastName">성</label>
<input
type="text"
id="lastName"
name="lastName"
value={formik.values.lastName}
onChange={formik.handleChange}
/>
{formik.touched.lastName && formik.errors.lastName && <span role="alert">{formik.errors.lastName}</span>}
이제 Yup을 사용해서 유효성 검사를 해보자
import * as Yup from 'yup'
Yup의 validationSchema를 사용해서 유효성 검사를 진행하려 한다.
기존의 validate를 대신해 validationSchema를 사용하자.
const validationSchema = Yup.object({
firstName: Yup.string()
.max(2, '성은 최대 2글자 입니다.')
.required('Required'),
lastName: Yup.string()
.required('Required'),
email: Yup.string().email('이메일 입력 형식이 올바르지 않습니다. 확인 후, 다시 입력하세요.').required('Required'),
}),
const formik = useFormik({
initialValues,
validationSchema, //validate 삭제 후 입력
onSubmit,
})
Formik 공식문서에서는 Yup 은 100% 옵션이라고 한다. 하지만 위에서 볼 수 있듯이 Yup을 사용하게 되면 코드를 많이 줄일 수 있다고 한다.
onChange -> handleChange, onBlur -> handleBlur등 이런 코드들은 Formik이 하는 일에 대해 매우 명시적이다.
useFormik()은 formik.getFieldProps()를 사용해서 더 빠르게 적용할 수 있도록 할 수 있다.
<label htmlFor="lastName">성</label>
<input
type="text"
id="lastName"
name="lastName"
//value={formik.values.lastName}
//onChange={formik.handleChange}
{...formik.getFieldProps('lastName')}
/>
{formik.touched.lastName && formik.errors.lastName && <span role="alert">{formik.errors.lastName}</span>}
이제 Formik 라이브러리가 제공하는 컴포넌트를 사용해서 폼을 컨트롤 해보자
import { Formik, Form, Field, ErrorMessage } from 'formik'
기본 적으로 Field는 input을 렌더링 한다. name props를 전달하면 암시적으로 각각의 onChange, onBlur, value props를 연결한다.
이 외의 as, className props들도 사용 가능하다.
<Formik
initialValues={initialValues}
validationSchema={validationSchema}
onSubmit={onSubmit}
>
<Form>
<label htmlFor="firstName">이름</label>
<Field
type="text"
id="firstName"
name="firstName"
//className
//as
/>
<ErrorMessage name="name" component={ErrorMessageComponent} />
</Form>
</Formik>
여기서 사용한 ErrorMessage 컴포넌트를 커스텀하기 위해 component 속성에 커스텀 컴포넌트를 연결한다.
const ErrorMessageComponent = (props) => <span role="alert" {...props} />
Yup 메서드
oneOf
language: Yup.string().oneOf(['javascript', 'c', 'c++', 'java']) // 배열에 입력한 항목 중 하나를 선택 해야 할 때 사용한다.
'라이브러리' 카테고리의 다른 글
react-helmet (0) | 2021.09.12 |
---|