UseForm이란 React에서 form의 validation을 도와주는 라이브러리이다. 이 라이브러리를 사용할 경우 하나의 객체를 선택적 인수로 사용한다.
설치 방법 : npm install react-hook-form
UseForm을 사용하지 않을 때의 회원가입 코드는 다음과 같이 복잡하게 작성했었다. 아래는 상태이상관리를 사용하지 않았어서 state를 남발하는 코드를 보여줬었다.
import { useState, useEffect } from "react";
import { useNavigate } from "react-router-dom";
const Create = () => {
const navigate = useNavigate();
////엄청나게 많은 useState들..
const [isEmail, setIsEmail] = useState(false);
const [isNumber, setIsNumber] = useState(false);
const [isPassword, setIsPassword] = useState(false);
const [passwordMessage, setPasswordMessage] = useState("");
const [emailMessage, setEmailMessage] = useState("");
const [state1, setState1] = useState(false);
const [state2, setState2] = useState(false);
const [theme, setTheme] = useState(localStorage.getItem("theme"));
useEffect(() => {
localStorage.setItem("theme", theme);
document.body.className = theme;
}, [theme]);
const handleInputId = (e) => {
setInputId(e.target.value);
if (e.target.value.length < 2 || e.target.value.length > 8) {
setIsId(false);
} else {
setIsId(true);
}
//-------------------생략---------------------
const onChangePassword = (e) => {
setInputPw(e.target.value);
const passwordRegExp =
/^(?=.*[a-zA-Z])(?=.*[!@#$%^*+=-])(?=.*[0-9]).{8,25}$/;
if (!passwordRegExp.test(inputPw)) {
setPasswordMessage(
"숫자+영문자+특수문자 조합으로 8자리 이상 입력해주세요!"
);
} else {
setPasswordMessage("안전한 비밀번호 입니다.");
setIsPassword(true);
}
};
return (
<div className={`${theme}`}>
<h1 class="my-5 py-2 text-xl text-center">회원가입</h1>
<h2 class="px-10 text-lg font-semibold buri">계정</h2>
<div class="py-5 flex justify-center">
<input
class="rounded text-sm border-b-2 w-1/2 leading-loose bg-transparent border-[#989898]"
placeholder="이메일을 입력해주세요"
type="text"
name="input_email"
value={inputEmail}
onChange={handleInputEmail}
/>
<button
onClick={onChangeEmail}
class="ml-2 text-center border rounded-full text-red-300 w-1/4 border-red-300 dark:bg-[#323435]"
>
인증번호 전송
</button>
//-----------생략-------------
이때는 깔끔하지 못한 코드를 적었었고 유효성도 각각 함수를 만들어서 state에 값을 넣는 비효율적인 방식을 사용했었다.🥺
react-hook-form패키지로부터 useForm() 훅(hook)함수를 불러온 후, 컴포넌트 함수안에서 이 함수를 호출하는 형식이다.
useForm()에는 여러 return props를 가지고 있는데 그 중 register과 formState, watch, setValues를 이용했다. 초기세팅은 다음과 같이 진행했다.
🚨유의점 : 해당코드는 tsx형식으로 작성되었다.
또한 handleSubmit을 보통 많이 사용하지만 axios사용시 서버와의 에러로 인해서 다른 방식으로 넘기게 되었다. handleSubmit을 활용하여 fetch방식으로 넘겨서 작동이 잘 되었던 코드는 로그인 게시글 때 올릴 예정이다.
interface UserValue {
email: string;
password: string;
nickname: string;
passwordConfirm: string;
idCheck: boolean;
emailCheck: boolean;
numberCheck: boolean;
}
function CreatePage() {
const regExpEm =
/^[A-Za-z0-9_]+[A-Za-z0-9]*[@]{1}[A-Za-z0-9]+[A-Za-z0-9]*[.]{1}[A-Za-z]{1,3}$/;
const regExgPw = /^(?=.*[a-zA-Z])(?=.*[!@#$%^*+=-])(?=.*[0-9]).{8,25}$/;
const {
register,
watch,
setValue,
formState: { errors, isValid },
} = useForm<UserValue>({
mode: "onChange",
});
}
Fuction | 내용 |
---|---|
register | input 요소를 React hook form과 연결시켜줌으로써, 검증 규칙을 적용할 수 있게 하는 메소드이다. |
watch | form state에 관한 정보를 담고 있는 객체이다. |
setValue | 지정된 입력을 읽고, 해당 값을 반환한다. 입력 값을 렌더링하고 조건별로 무엇을 렌더링할지 결정하는 데 사용한다. |
formState | 등록된 필드의 값을 동적으로 설정하고, 양식 상태를 확인하고 업데이트하는 기능이다. |
해당 useForm은 onChange가 발생할 때 validation을 발생시키도록 하였다. mode는 useForm()에 넘겨줄 수 있는 다양한 optional arguments 중 하나로 사용자가 form을 submit 하기 전에 validation이 실행될 수 있게 해준다.
<LoginInputDiv>
<CreateStyledInput
placeholder="이메일을 입력해주세요"
type="email"
id="userEmail"
required
{...register("email", { required: true, pattern: regExpEm })}
/>
<CreateStyledInputButton onClick={emailCheck}>
인증번호 전송
</CreateStyledInputButton>
</LoginInputDiv>
{errors.email?.type === "required" && (
<ErrorDiv>이메일을 입력해주세요</ErrorDiv>
)}
{errors.email?.type === "pattern" && (
<ErrorDiv>잘못된 이메일 형식입니다</ErrorDiv>
)}
//....
register 메소드를 사용해서 input 요소를 React hook form에 등록해준다. 이 때 validation도 같이 시행해주기 위해서 필수 항목 입력을 하게 해주는 required와 유효성 검사를 도와주는 pattern을 활용하였다.
required ? 입력에 값이 있어야 양식을 제출할 수 있음을 나타내는 boolean이다. 오류 개체에서 오류 메시지를 반환하는 문자열을 할당할 수 있다.
pattern ? 입력에 대한 정규식 패턴을 넣을 수 있다.
이 이외에도 maxLength, minLength 등 다른 방법도 있고 validate을 직접 만들어줄 수 있다.
🚨문제점🚨 : 기존에 사용했던 fetch가 아닌 axios로 바꿔서 API를 보낸 결과, handleSubmit방식이 fetch에서는 되지만 axios에서는 500에러가 나는 문제가 존재했었다.
✅임시해결방법✅ : watch를 활용해서 값을 넘겨주었다. submit방식을 활용하지 못한 건 아쉽지만 axios를 이번 프로젝트에 도입할 것이기 때문에 오류를 일으키지 않는 방향으로 가기로 하였다.
handleSubmit방식은 Login에서 fetch방식으로 보여줄 예정이다. 이번 방식은 axios를 활용한 watch와 setValues의 사용방식을 보여줄 것이다.
const emailCheck = (e: React.MouseEvent<HTMLButtonElement>) => {
e.preventDefault();
axios
.post(
"https://seohamserver.shop/mail/send",
{
email: watch("email"),
},
{ headers: { "Content-Type": "application/json" } }
)
.then((res) => {
if (res.status === 200) {
window.alert("사용가능한 이메일입니다.인증번호를 보냈습니다");
setValue("emailCheck", true);
} else {
window.alert("이미 사용중이거나 유효하지 않는 이메일입니다");
setValue("emailCheck", false);
}
});
};
//...
const clickSignUp = (e: React.MouseEvent<HTMLButtonElement>) => {
e.preventDefault();
if (
watch("emailCheck") === false ||
watch("idCheck") === false ||
watch("numberCheck") === false ||
watch("password") !== watch("passwordConfirm")
) {
alert("유효성 검사 및 비밀번호중복확인을 완료해주세요");
} else {
axios
.post("${API주소}/user/join", {
email: watch("email"),
passWord: watch("password"),
nickName: watch("nickname"),
})
.then((res) => {
if (res.status === 200) {
alert("가입이 완료되었습니다");
navigate("/");
} else {
alert("조금 있다가 시도해주세요");
}
});
}
};
//.....
return(
//.....
<LongInputDiv>
<LoginButton type="submit" disabled={!isValid} onClick={clickSignUp}>
확인
</LoginButton>
</LongInputDiv>
)
인증번호를 하기 위해서는 실제 이메일을 사용해야하기 때문에 나중에 로그인까지 완료가 되면 그 때 실행할 예정이다. 지금은 react hook form으로 register와 validation이 어떻게 이루어지는지를 보면 된다.😍
다음에는 Login부분을 handleSubmit방식과 함께 다룰 예정이다.
감사합니다 배워갑니다! 좋은 한 주 되세요 ☺️