본문 바로가기

WEB/JavaScript

[JS] Formik

 

Formik과 Yup은 Form 작업을 좀 더 편리하게 해주는 라이브러리이다.

Formik에 공식문서에는 Form 작업을 할때 가장 성가신 작업이 3가지로 분류된다고 한다.

  • 폼에서 값 가져오기
  • 유효성 검사 및 오류 메세지
  • 폼 submit 핸들링

Formik

먼저 설치하는 방법은 터미널에 입력한다.

 

npm install formik

 

위에서 설명 했듯이 폼에서 입력한 데이터를 받는 역할을 하고 유효성 검사와 오류 메세지를 동적으로 띄워줄 수 있다.

Form 기능이 그러하듯 버튼을 클릭하면 Form에 입력한 값들을 객체로 담아 처리할 수 있도록 해준다.

이 기능을 좀 더 간편하게 할 수 있는데 사실 차이가 그렇게 크지 않아서 사용을 하지 않아도 된다.

 

import React from "react";

/* Lib */
import * as Yup from 'yup';
import { registerUser } from "../_actions/user_actions";
import { useDispatch } from "react-redux";

/* Components */
import { Formik } from 'formik';
import { LockOutlined, MailOutlined, UserOutlined } from "@ant-design/icons";

function RegisterPage(props) {
  const dispatch = useDispatch();
  return (

    <Formik
      initialValues={{
        email: '',
        name: '',
        password: '',
        confirmPassword: ''
      }}
      
      validationSchema={Yup.object().shape({
        name: Yup.string()
          .required('이름을 입력하지 않았습니다.'),
        email: Yup.string()
          .email('이메일 형태가 아닙니다.')
          .required('이메일을 입력하지 않았습니다.'),
        password: Yup.string()
          .min(6, '패스워드는 6자리 이상 입력해주세요.')
          .required('패스워드를 입력하지 않았습니다.'),
        confirmPassword: Yup.string()
          .oneOf([Yup.ref('password'), null], '패스워드와 일치하지 않습니다.')
          .required('패스워드 확인을 입력하지 않았습니다.')
      })}

      onSubmit={(values, { setSubmitting }) => {
        setTimeout(() => {

          let dataToSubmit = {
            email: values.email,
            password: values.password,
            name: values.name,
            lastname: values.lastname,
          };

          dispatch(registerUser(dataToSubmit)).then(response => {
            if (response.payload.success) {
              props.history.push("/login");
            } else {
              alert(response.payload.message)
            }
          })

          setSubmitting(false);
        }, 500);
      }}
    >
      {props => {
        const {values, touched, errors, isSubmitting, handleChange, handleBlur, handleSubmit, } = props;
        return (
          <div className="app">

            <Form style={{ maxWidth: "25rem", margin: '10rem auto' }} {...formItemLayout} onSubmit={handleSubmit} >
              <Title level={2}>회원가입</Title>

              <Form.Item required label="이름">
                <Input
                  id="name"
                  placeholder="이름"
                  type="text"
                  value={values.name}
                  onChange={handleChange}
                  onBlur={handleBlur}
                  prefix={<UserOutlined className="site-form-item-icon" />}
                  className={
                    errors.name && touched.name ? 'text-input error' : 'text-input'
                  }
                />
                {errors.name && touched.name && (
                  <div className="input-feedback">{errors.name}</div>
                )}
              </Form.Item>

              <Form.Item required label="Email" hasFeedback validateStatus={errors.email && touched.email ? "error" : 'success'}>
                <Input
                  id="email"
                  placeholder="Email Adress"
                  type="email"
                  value={values.email}
                  onChange={handleChange}
                  onBlur={handleBlur}
                  prefix={<MailOutlined />}
                  className={
                    errors.email && touched.email ? 'text-input error' : 'text-input'
                  }
                />
                {errors.email && touched.email && (
                  <div className="input-feedback">{errors.email}</div>
                )}
              </Form.Item>

              <Form.Item required label="비밀번호" hasFeedback validateStatus={errors.password && touched.password ? "error" : 'success'}>
                <Input
                  id="password"
                  placeholder="비밀번호"
                  type="password"
                  value={values.password}
                  onChange={handleChange}
                  onBlur={handleBlur}
                  prefix={<LockOutlined className="site-form-item-icon" />}
                  className={
                    errors.password && touched.password ? 'text-input error' : 'text-input'
                  }
                />
                {errors.password && touched.password && (
                  <div className="input-feedback">{errors.password}</div>
                )}
              </Form.Item>

              <Form.Item required label="비밀번호 확인" hasFeedback>
                <Input
                  id="confirmPassword"
                  placeholder="비밀번호 다시 입력해주세요"
                  type="password"
                  value={values.confirmPassword}
                  onChange={handleChange}
                  onBlur={handleBlur}
                  prefix={<LockOutlined className="site-form-item-icon" />}
                  className={
                    errors.confirmPassword && touched.confirmPassword ? 'text-input error' : 'text-input'
                  }
                />
                {errors.confirmPassword && touched.confirmPassword && (
                  <div className="input-feedback">{errors.confirmPassword}</div>
                )}
              </Form.Item>

              <Form.Item {...tailFormItemLayout}>
                <Button onClick={handleSubmit} type="primary" disabled={isSubmitting}>
                  회원가입
                </Button>
              </Form.Item>
            </Form>
          </div>
        );
      }}
    </Formik>
  );
};

export default RegisterPage

 

위 컴포넌트는 회원가입을 Formik과 Yup으로 구현해놓은 코드이다.

 

Form, Form.Item은 Ant Design 컴포넌트 이므로 무시하자. 중요한건 Input과 Formik이다.

위 코드에서 Formik에 대해서 중요시 봐야할건 Formik이 하나의 컴포넌트이다. Formik 컴포넌트가 Form을 감싸고 있는 형태이다. 또한 initialValues 이벤트는 Form내에서 핸들링할 Value들을 선언하는 것이다. (useFormik() 훅을 선언해서 Form Data를 가져오는 방법또한 있다.)

 

이후 props에서 이벤트와 상태들을 가져올 수 있다.(자세한건 공식문서에 있다.)

 

| Formik

Copyright © 2020 Formium, Inc. All rights reserved.

formik.org

 

input 태그에서 id를 값이 들어가길 원하는 initialValue key 값과 동일하게 한뒤 props에서 가져온 onChange 핸들러를 설정 해주면 각각  initalValue에 들어가게 된다. 

이렇게 값을 가져와서 handleSubmit과 연결된 Formik의 onSubmit 함수를 통해서 서버에 요청을 보내주는 구조이다.

유효성 테스트는 Yup이 담당한다.