Jaeilit

formik 적용하기 본문

TIL

formik 적용하기

Jaeilit 2021. 11. 5. 13:15
728x90

공식문서

https://formik.org/

 

Formik

React hooks and components for hassle-free form validation. The world's leading companies use Formik to build forms and surveys in React and React Native.

formik.org

 

기존코드

 

export const Login = (props) => {
  const { history } = props

  const [loginOther, setLoginOther] = useState(false)

  const [inputValue, setInputValue] = useState({
    userid: "",
    password: "",
  })

  const { userid, password } = inputValue

  const idCehcking = userid !== "" && emailCheck.test(userid)
  const passwordChecking = password !== "" && passwordCheck.test(password)

  const onChangeValue = (e) => {
    const { name, value } = e.target
    setInputValue({
      ...inputValue,
      [name]: value,
    })
  }

 

기존에는 입력을 여러개 받기 위해서 useState({})를 객체화 해서 사용했습니다.

 

그리고 로그인 시 입력 체크를 따로 변수 값으로 둬야했습니다.

 {/* 입력오류 문구 */}
        {!idCehcking && (
          <Text color="#FB1F07" size="9px">
            이메일 양식을 확인해주세요
          </Text>
        )}

또 입력 오류시 문구 또한 태그마다 걸어줘야했습니다.

 

그러다 보니 코드는 자연스레 길어졌고 가독성 또한 떨어지면서 저도 혼란스러워질정도 였습니다.

 

이 문제에 대해 리팩토링이 필요하다 느꼈고, 

 

formValidation 을 찾던 중

formik 과 react-hook-form 을 알게 되었는데

formik 의 사용자가 압도적으로 많다는 블로그 글을 보고 formik을 적용해보기로 마음 먹었습니다.

 

개인적으로 formik 자체도 한글문서가 없고 구글링으로 통해 블로그를 여러개 다녀봤지만 감이 오지않아서

유투브를 찾아봤습니다.

유투브에서 여전히 한국사람보다 외국분들것이 많아서 자막 틀고 코드를 익혔습니다.

 

혹시 참고가 될만할까해서 제가 본 유튜브 주소도 공유합니다.

https://www.youtube.com/watch?v=u-CCnDayNJw 

 

리팩토링 후 코드

 const validate = Yup.object({
    email: Yup.string().email("이메일 형식으로 입력해주세요.").required(""),
    password: Yup.string()
      .matches(
        emailCheck,
        "영문 + 특수문자 + 숫자 포함 8글자 이상의 비밀번호를 설정해주세요."
      )
      .required(""),
  })

  return (
    <Container>
      <Logo>야구메이트</Logo>
      <Formik
        initialValues={{
          email: "",
          password: "",
        }}
        validationSchema={validate}
      >
      
      //번외 회원가입에 있는 코드 비밀번호 체크  
      confirmPassword: Yup.string()
      .oneOf([Yup.ref("password"), null], "비밀번호가 일치하지 않습니다.")
      .required(""),

바뀐부분 위주로 올렸습니다.

 

1. return 문 안의 Formik 의 initialValues 안에 초기 값들을 설정해줍니다. 저는 이메일과 패스워드 입니다.

2. validationSchema={validate} 이 부분은 유효성 검사 부분입니다.

 

Yup.object객체 안에서 email, password에 대한 유효성 검사와 에러멘트를 만듭니다.

 

email.string().email() : 이메일 형식이 아닐 때 메세지

required("") : 입력 값이 없을 때 메세지 

matches() : 정규식을 사용 할 시에는 matches 해주시고 정규식을 넣어주시면 됩니다.

oneof([Yup.ref("비교 값"), null 에러 문구 

 

리팩토링이 어떻게 되었는가?

기존코드

<Inputs
          name="userid"
          type="text"
          value={userid}
          onChange={onChangeValue}
          placeholder="아이디로 사용할 이메일을 입력해주세요"
        >
          이메일
          {/* 입력체크표시 */}
          {idCehcking && <InputCheck />}
        </Inputs>

        {/* 입력오류 문구 */}
        {!idCehcking && (
          <Text color="#FB1F07" size="9px">
            이메일 양식을 확인해주세요
          </Text>
        )}

        <Inputs
          name="password"
          check
          type="password"
          value={password}
          onChange={onChangeValue}
          placeholder="영문 + 특수문자 + 숫자 포함 8글자 이상의 비밀번호를 설정해주세요."
        >
          비밀번호
          {/* 입력체크표시 */}
          {passwordChecking && <InputCheck />}
        </Inputs>
        {/* 입력오류 문구 */}
        {!passwordChecking && (
          <Text color="#FB1F07" size="9px">
            영문 + 특수문자 + 숫자 포함 8글자 이상의 비밀번호를 설정해주세요.
          </Text>
        )}

 

formik 코드

 {(formik) => (
          <Form>
            {/* {console.log(formik.values, "login")} */}
            <TextField
              label="이메일"
              name="email"
              type="email"
              placeholder="아이디로 사용 할 이메일을 입력해주세요"
            />

            <div style={{ position: "relative" }}>
              <TextField
                label="비밀번호"
                name="password"
                type={showPwd ? "text" : "password"}
                placeholder="비밀번호를 입력해주세요"
              />
              <IoEyeSharp
                size="24"
                style={{
                  position: "absolute",
                  right: "10px",
                  top: "42px",
                }}
                onClick={() => {
                  setShowPwd(!showPwd)
                }}
              ></IoEyeSharp>
            </div>

 

TextField Components

export const TextField = ({ label, ...props }) => {
  const [field, meta] = useField(props)

  console.log("meta", meta)

  return (
    <InputBox>
      <label htmlFor={field.name}>
        {label}
        {!meta.error && meta.touched && meta.value !=="" ? (
          <InputCheck />
        ) : null}
      </label>
      <Input type={props.type} {...field} {...props} />

      <Text color="#FB1F07" size="9px" margin="6px 0">
        <ErrorMessage name={field.name} />
      </Text>
    </InputBox>
  )
}

 

1. 사용방법

Formik 설치 후 

 

Formik 태그와 Form 태그로 감싼 뒤

 

<TextField Components를 사용합니다.>

label = 라벨이름

name = "type명"

type="type명"

 

name은 error메세지 meta태그 등등의 이유로 type 명과 같아야합니다.

 

이렇게만하면 input 설정은 끝납니다.

 

기존코드와 달리 onChange를 안걸어줘도 되고 value를 따로 설정하지 않으셔도 됩니다.

정말 간단합니다.

 

TextField로 넘어가보겠습니다.

props로 넘겨받은 label, name, type등을 활용하고, meta태그를 활용합니다.

meta태그 내에는 이러한 정보들이 담겨있습니다.

저희가 알아두면 좋은 메서드는 touched 와 value, error 정도 입니다.

touched 는 말 그대로 터치했냐라는 의미입니다. 포커스와 비슷합니다.

value는 입력값입니다.

error는 error 의 유무가 아닌 에러 메세지내용을 말합니다.

 

알아두면 좋은 이유는 아래에서 설명 드립니다.

 

1. <ErrorMessage>가 메타태그의 error touched 의 종합입니다.

 <ErrorMessage component="div" name="email" />
 // --> {touched.email && error.email ? <div>{error.email}</div> : null}

<ErrorMessage> 태그의 간편함,

 

본래 기존 코드에서는 에러메세지를 input 태그 마지막단에 하나씩 넣어줬습니다.

하지만 formik을 쓰면 TextField 내에 불러오면 됩니다.

 

https://formik.org/docs/api/errormessage 

 

| Formik

Copyright © 2020 Formium, Inc. All rights reserved.

formik.org

2. 디스패치 할 경우 값을 넘길 때

 _onClick={() => {
                dispatch(
                  userActions.logInMD({
                    userid: formik.values.email,
                    password: formik.values.password,
                  })
                )

formik.values 라는 이 코드는 TextField 의 meta 객체 안의 값들은 아닙니다.

 

하지만 위의 meta코드의 values와는 같습니다.

TextField에서는 useField() 로 meta를 받아 왔기 때문에 meta.values 입니다.

728x90

'TIL' 카테고리의 다른 글

클립 메타태그og  (0) 2021.11.12
환경변수때문에 해맨 ssul  (0) 2021.11.08
이미지 미리보기 업로드 Axios, React  (0) 2021.11.05
TIL 카카오 로그인 구현(인가코드받기)  (0) 2021.11.04
인풋 여러개 쓰기 REACT  (0) 2021.10.28