요번한주를 개인적으로 정리하는 글입니다
React-Hook-Form 라이브러리 알아보기 및 사용하기
React-Hook-Form 이란?
React 에서 폼 양식을 만들때 사용하는 라이브러리입니다
복잡한 폼을 만들때, 코드를 간결하게 만드는데 도움을 줍니다
React-Hook-Form 사용법
npm install react-hook-form
or
yarn add react-hook-form
React-Hook-Form 을 사용하기 전
function Login() {
const [userEmail, setUserEmail] = useState("");
const [password, setPassword] = useState("");
const [nickname, setNickName] = useState("");
const [phoneNumber, setPhonNumber] = useState("");
const [toDo, setToDo] = useState("");
const submit = () => {
if (userEmail === "" || password === "" || nickname === "" || phoneNumber) {
window.alert("입력칸들을 전부 입력해주세요!");
}
if (!emailCheck(userEmail)) {
window.alert("이메일 형식이 맞지 않습니다!");
return;
}
if (!passwordCheck(password)) {
window.alert(
"비밀번호는 숫자와 문자 포함 형태의 6~12자리 이내로 가능합니다!"
);
return;
}
if (!nickCheck(nickname)) {
window.alert("닉네임은 한글, 영문, 숫자만 가능하며 2-10자리 가능합니다!");
return;
}
if (!phoneCheck(phoneNumber)) {
window.alert("핸드폰번호는 000-0000-0000 의 형태로 숫자를 입력해주세요");
return;
}
};
const onEmailChange = (event: React.FormEvent<HTMLInputElement>) => {
const {
currentTarget: { value },
} = event;
setUserEmail(value);
};
const onPwChange = (event: React.FormEvent<HTMLInputElement>) => {
const {
currentTarget: { value },
} = event;
setPassword(value);
};
const onNickChange = (event: React.FormEvent<HTMLInputElement>) => {
const {
currentTarget: { value },
} = event;
setNickName(value);
};
const onPhonChange = (event: React.FormEvent<HTMLInputElement>) => {
const {
currentTarget: { value },
} = event;
setPhonNumber(value);
};
const onChange = (event: React.FormEvent<HTMLInputElement>) => {
const {
currentTarget: { value },
} = event;
setToDo(value);
};
const onSubmit = (event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault();
console.log(userEmail);
console.log(password);
console.log(nickname);
console.log(phoneNumber);
console.log(toDo);
};
return (
<div>
<FormMain onSubmit={onSubmit}>
<input
onChange={onEmailChange}
value={userEmail}
placeholder={"이메일을 입력해주세요"}
/>
<input
onChange={onPwChange}
value={password}
placeholder={"비밀번호를 입력해주세요"}
/>
<input
onChange={onNickChange}
value={nickname}
placeholder={"별명을 입력해주세요"}
/>
<input
onChange={onPhonChange}
value={phoneNumber}
placeholder={"핸드폰 번호를 입력해주세요"}
/>
<input
onChange={onChange}
value={toDo}
placeholder="내용을 입력해주세요"
/>
<button onClick={submit}>제출하기</button>
</FormMain>
</div>
);
}
- 상태를 가져오기위한 useState 사용
- 정해진 규칙으로 작성된지를 검증하기위한 정규식 사용
- 이벤트를 적용하기위한 onChange, onClick 이벤트 사용
- 사용자의 입력값들 받기위한 form input 사용
위에 작성된 코드들을 보면 검증과 입력값을 받기위해 많은 코드들이 작성되어야 합니다
작성한 코드들의 화면들
입력값을 빼놓고 입력하지 않았을 시 경고창

이메일을 정해진 규칙대로 작성하지않았을경우 나오는 경고창

비밀번호를 정해진 규칙대로 작성하지않았을경우 나오는 경고창

닉네임을 정해진 규칙대로 작성하지않았을경우 나오는 경고창

핸드폰번호를 정해진 규칙대로 작성하지않았을경우 나오는 경고창

모두 입력시 콘솔에 나오는 입력값들

React-Hook-Form 을 사용하기 후
interface IForm {
email: string;
firstName: string;
lastName: string;
username: string;
password: string;
password1: string;
extraError?: string;
}
function ToDoList() {
const {
register,
handleSubmit,
formState: { errors },
setError,
} = useForm<IForm>({ defaultValues: { email: "@naver.com" } });
const onValid = (data: IForm) => {
if (data.password !== data.password) {
setError(
"password1",
{ message: "Password are not the same" },
{ shouldFocus: true }
);
}
};
return (
<div>
<form
style={{ display: "flex", flexDirection: "column" }}
onSubmit={handleSubmit(onValid)}
>
<input
{...register("email", {
required: "Email is required",
pattern: {
value: /^[A-Za-z0-9._%+-]+@naver.com$/,
message: "Only naver.com emails allowed",
},
})}
placeholder="Email"
/>
<span>{errors?.email?.message}</span>
<input
{...register("firstName", {
required: "write here",
validate: {
noNico: (value) =>
value.includes("nico") ? "no nicos allowed" : true,
noNick: (value) =>
value.includes("nick") ? "no nick allowed" : true,
},
})}
placeholder="First Name"
/>
<span>{errors?.firstName?.message}</span>
<input
{...register("lastName", { required: "write here" })}
placeholder="Last Name"
/>
<span>{errors?.lastName?.message}</span>
<input
{...register("username", { required: "write here", minLength: 10 })}
placeholder="Username"
/>
<span>{errors?.username?.message}</span>
<input
{...register("password", { required: "write here", minLength: 5 })}
placeholder="Password"
/>
<span>{errors?.username?.message}</span>
<input
{...register("password1", {
required: "Password is required",
minLength: {
value: 5,
message: "Your password is too short.",
},
})}
placeholder="Password1"
/>
<span>{errors?.password?.message}</span>
<button>Add</button>
<span>{errors?.extraError?.message}</span>
</form>
</div>
);
}
Form 으로 입력받을 데이터 타입 정의하기
react-hook-form 에서 import 한 useForm 사용하기
- register 는 리액트훅폼에게, 이 인풋에 대해 이러한 항목을 입력받을 것이라는 것을 등록해준다. ( onChange => register )
- handleSubmit 은 리액트훅폼에서 각 항목이 입력되었을 때 submit 이벤트를 처리하는 역할을 한다. ( onSubmit => handleSubmit )
- watch 는 register 한 항목의 변경사항을 관찰한다. ( useState => watch )
- errors 는 유효성이 통과되지 않으면 에러 상태를 내보내준다.
1. onChange => register
useform 은 많은것들을 제공합니다 ( register 함수 )
register 함수의 사용으로 onChange 이벤트 핸들러의 필요성이 사라집니다
( props 로 주는 값들도 마찬가지 예) [item,setItem] = state("") )
function ToDoList() {
const { register, watch } = useForm();
return (
<div>
<form>
<input {...register("toDo")} placeholder="Write a to do" />
<button>Add</button>
</form>
</div>
);
}
2. useState => watch
useform 은 많은것들을 제공합니다 ( watch )
watch 는 form 의 입력값들의 변화를 관찰할수있게 해주는 함수입니다
input 에 값을 적기 시작하면 toDo를 키값으로 가지는 객체가 있으며 toDo키는 사용자가 적은 입력값을 value 값으로 가지고있습니다
register로 한줄의 코드를 적기만하면 state를 만들어줍니다
react-hook-form 을 쓰기전에는 onChange 이벤트함수를 만들고 input에 props를 줘서 사용하고 useState로 상태가 변화할시 입력값을 가져오는 변수를 만들어줬지만 react-hook-form 을 사용하고서부터는 onChange를 사용하지않고 register로 사용후 변화하는값을 watch 로 관찰하여 추적할수있습니다
결과적으로는 input이 하나밖에 없을경우 react-hook-from 이 필요하지 않을수도 있습니다
하지만 로그인 페이지를 만들어 입력값이 많아질경우 사용자에게 입력값을 받아올수있는 input 태그가 많아질것입니다
그로인해 상태를 관리하기위한 useState변수와 입력값을 받아오기위해 생기는 변수가 많아져 코드가 길어지는 상황이 발생합니다
react-hook-from 을 사용해서 위와같이 한개의 변수 사용과 많은 input 코드가 짧아질수있습니다
react-hook-from 의 사용으로 여러가지의 input 태그를 다룰수있습니다
3. onSubmit => handleSubmit
handleSubmit 는 validation ( 확인 ) 을 담당하고 이벤트를 preventDefault ( 기본동작을 막음 ) 하는것도 담당합니다
eventpreventDefault() 는 어떤 이벤트를 명시적으로 처리하지않는 경우 해당 이벤트에 대한 사용자의 기본동작을 실행되지않도록 막는것입니다
eventpreventDefault() 를 이전에 사용했던 이유는 이벤트가 중복처리되어서 사용하게되었습니다 ( 이벤트 버블링 )
이벤트 버블링 = 특정 화면 요소에서 이벤트가 발생했을 떄 해당 이벤트가 더 상위의 화면 요소들로 전달되어 가는 특성

handleSubmit 는 2개의 인자를 받습니다
1. 데이터가 유효할때 호출되는 함수 = onValid
2. 데이터가 유효하지않을때 호출되는 함수 = onInvalid
onInvalid 는 필수는 아니지만 onValid는 필수입니다
button으로 onSubmit 가 실행되면 handleSubmit 가 실행되면서 마지막으로 onValid가 불러집니다
const { register, handleSubmit, formState } = useForm();
const onValid = (data: any) => {
console.log(data);
};
<input
{...register("firstName", { required: true })}
placeholder="First Name"
/>
required : true가 있으면 비어있지않으면 통과되고 비어있으면 submit 버튼을 눌러도 통과되지않는다
<input
{...register("lastName", { required: true })}
placeholder="Last Name"
/>
<input
{...register("username", { required: true, minLength: 10 })}
placeholder="Username"
/>
required: true, minLength: 10 <- 이렇게되어있으면 10글자까지 작성해야 submit 버튼을 누를수있고
{ required: true, minLength: 5 } <- 최소 5글자 제한이다
<input
{...register("password", { required: true, minLength: 5 })}
placeholder="Password"
/>
<input
{...register("password1", {
required: "Password is required",
minLength: {
value: 5,
message: "Your password is too short.",
},
})}
placeholder="Password1"
/>
패스워드1 에 글자수 5글자제한에 메세지로 Your password is too short 라고 보내지게되며
모든조건이 통과시 submit버튼을 눌러 정보를 보낼수있다
위와같이 작성되면 handleSubmit 로 인하여 작동하게됩니다
hanleSubmit 는 required 나 minLength , maxLength 등이 있으며 사용방법은 2가지의 방법이 있습니다
{required : true} <- 이와 같이 사용시 적용된 input 값이 필수로 들어가야한다
{required:" your password empty "}
위와 같이 사용시 적용된 input 값이 없을경우 유저에게 보여줄 화면에 나올 에러객체에 들어가게된다
minLength 에는 2가지 옵션이 있습니다
1. 최소 글자수 보내기
2. 객체를 보내기 ( 객체안에는 값을 보낼수있고 사용자에게 메세지를 보낼수있다)
또 다른 확인( 검증 ) 방법이있는데 그 방식은 위에서 사용했듯 정규식의 사용방법이다
<input
{...register("password", { required: "write here", minLength: 5 })}
placeholder="Password"
/>
<span>{errors?.password?.message}</span>
위와 같이 사용시 인풋의 적는값은 password 고 필수사항으로 write here 을 보여주고
최소길이 5자이상으로 잡아주며 그냥 제출시 errors가 보여 write here 이 보일수있도록 만든 코드이다
실행 화면

'프로그램 시작후 각 주차 정리' 카테고리의 다른 글
| 공부 16주차 코드 스테이츠 (1주) (0) | 2022.06.25 |
|---|---|
| 공부 14주차 - coin tracker 만들기 (0) | 2022.06.11 |
| 공부 13주차 - part 1 ( ApexCharts , Recoil ) (0) | 2022.06.04 |
| 공부 12주차 - part 2 ( React-Query ) (0) | 2022.05.29 |
| 공부 11주차 (0) | 2022.05.22 |