React Js Master #7 React-hook-form ,register,watch, ,handleSubmit, formState
react-hook-form
react에서 form 만들기 편한 방법 .
사용하기 쉬운 유효성 검사를 통해 성능이 뛰어나고 유연하며 확장 가능한 form.
이 것을 사용하지 않으면 많은 input form에 대해 일일이 useState() 사용 해야 함.
1.npm i react-hook-form
2. import {useForm } from "react-hook-form";
3.const { register } = useForm();
useForm의 register을 사용하면 onChange와 관련된 핸들러를 작성할 필요 없다.
function ToDoList() {
const { register } = useForm();
console.log(register("toDo"));
return (
<div>
<form>
<input
{...register("toDo")}
placeholder="Write a to do "
></input>
<button>Add</button>
</form>
</div>
);
}
4.const { watch } = useForm();
useForm의 또 다른 기능 watch.
form내 변화하는 모든 값을 관찰하는 함수 .
console.log하면 toDo라는 이름을 가진 변화된 값들이 나옴.
5. 많은 input에 대해 useState를 각각 써 줄 필요가 없음.
function ToDoList() {
const { register, watch } = useForm();
console.log(watch());
return (
<div>
<form>
<input {...register("Email")} placeholder="Email " />
<input {...register("firstName")} placeholder="firstName" />
<input {...register("lastName")} placeholder="lastName " />
<input {...register("ID")} placeholder="ID " />
<input {...register("password")} placeholder="Password " />
<button>Add</button>
</form>
</div>
);
}
6.const {handleSubmit}= useForm()
const {register ,handleSubmit}= useForm()
const onValid = (data: any) => {
console.log(data);
};
hanldesubmit(onValild , onInValid)
핸들서밋은 두가지 인자를 받는데 하나는 폼이 유효할 때, 유효하지 않을 때 함수이다.
전자는 필수이다.
preventDefault()자동으로 해줌
<input
{...register("Email", { required: true })}
placeholder="Email "
/>
<input
{...register("firstName", { required: true , minLength: 10})}
placeholder="firstName"
/>
<input requrired= true> 같이 html로 작성하면 누군가 소스코드에 수정 할 수 있고 지원하지 않는 브라우저나, 모바일 환경에 있을 수도 있으니 위와 같이 register내에 자바스크립트에서 설정함.
sumbit후 자동으로 required이 아닌 input에 자동 포커스
7.const { formState } = useForm()
유효성에 대한 에러를 보여줌
function ToDoList() {
const { register, handleSubmit, formState } = useForm();
console.log(formState.errors);
메세지도 담아서 보여줄 수 있다.
<input
{...register("password", {
required: "password is required",
minLength: { // 객체 형태
value: 5,
message: "your password is too short",
},
})}
placeholder="Password "
/>
register로 직접 등록해야할 이벤트 핸들러 , 유효성 검사등을 함
/* function ToDoList() {
const [toDo, setToDo] = useState("");
const [toDoError, setToDoError] = useState("");
const onChange = (event: React.FormEvent<HTMLInputElement>) => {
const {
currentTarget: { value },
} = event;
setToDoError("");
setToDo(value);
};
const onSubmit = (event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault();
if (toDo.length < 10) {
return setToDoError("To do should be longer");
}
console.log("submit");
};
return (
<div>
<form onSubmit={onSubmit}>
<input onChange={onChange} value={toDo} placeholder="Write a to do" />
<button>Add</button>
{toDoError !== "" ? toDoError : null}
</form>
</div>
);
} */ useForm을 사용하기 전에 쓰던 코드
또다른 vaildation 방법 : 정규표현식
이메일 유효성 검사시에 사용
<input
{...register("Email", {
required: true ,
pattern:/^[A-Za-z0-9._%+-]+@naver.com$/
})}
placeholder="Email "
/>
마찬가지로 객체형태로 메세지도 보낼 수 있음
<input
{...register("Email", {
required: true ,
pattern:{
value:/^[A-Za-z0-9._%+-]+@naver.com$/,
message: "Only naver.com email allowed"
}
})}
placeholder="Email "
/>
에러메세지 화면에 출력하기
function ToDoList() {
const {
register,
handleSubmit,
formState: { errors },
} = useForm();
const onValid = (data: any) => {
console.log(data);
};
return (
<div>
<form
style={{ display: "flex", flexDirection: "column" }}
onSubmit={handleSubmit(onValid)}
>
<input
{...register("email", {
required: "Email required",
pattern: {
value: /^[A-Za-z0-9._%+-]+@naver.com$/,
message: "Only naver.com email allowed",
},
})}
placeholder="Email "
/>
<span>{errors?.email?.message}</span>
알아서 메세지가 나타난다.
사용자가 작성하자마자 나타나는 것은 아니고
submit후에 react-form-hook이 작동
8.interface , generics , default value
interface IForm {
email: string;
firstName: string;
lastName: string;
ID: string;
password: string;
}
function ToDoList() {
const {
register,
handleSubmit,
formState: { errors },
} = useForm<IForm>({
defaultValues: {
email: "@naver.com",
},
});
정규표현식
^ 문장의 시작
[] : 문자셋 안의 아무문자
+ 하나 또는 하나이상
```
/^[A-Za-z0-9._%+-]+@naver.com$/
/^[A-Za-z0-9._%+-]+@naver.com/g
```
https://www.regexpal.com
React Hook Form (TypeScript)
React Hook Form은 TypeScript로 빌드되었으며, FormData 유형을 정의하여 form 값을 지원할 수 있습니다.
```
type FormData = {
firstName: string;
lastName: string;
};
const { register, setValue, handleSubmit, formState: { errors } } = useForm< FormData >();
```
https://react-hook-form.com/get-started#TypeScript
defaultValues: Record< string, any > = {}
input에 대한 defaultValues는 사용자가 component와 상호 작용하기 전에 component가 처음 렌더링될 때 초기 값으로 사용됩니다.
모든 input에 대한 defaultValues를 빈 문자열이나 null과 같은 정의되지 않은 값으로 설정하는 것이 좋습니다.
https://react-hook-form.com/api/useform#props
9.setError 특정 에러 발생시키기
back에서 에러가 나올 경우 error을 발생 시켜야함 .
직접 에러 발생 시키기
const onValid = (data: IForm) => {
if (data.password1 !== data.password2) {
setError("password1", { message: "Password are not same" });
}
};
setError()입력하면 IForm에 있는 항목들만 나온다 따라서 IForm에 새 항목 추가
interface IForm {
email: string;
firstName: string;
lastName: string;
ID: string;
password: string;
password2: string;
extraError?: string;
}
const onValid = (data: IForm) => {
if (data.password !== data.password2) {
setError("password", { message: "Password are not same" });
}
setError("extraError", { message: "Server offline" });
};
특정 항목에 대한 error가 아니고 form에 대한 error
<span>{errors?.extraError?.message}</span>
if (data.password1 !== data.password2) {
return setError(
"password1",
{ message: "Password are not same" },
{ shouldFocus: true } //문제가 생긴 곳에 focus 옮기기 password1로 옮겨감.
);
}
onValid => password비교하는 부분에서 처음 에러 출력되고, 이 후 Password 에러 출력안되시면 setError앞에 return 해주세요.
10.내가 원하는 아무 규칙에따라 validation 하기 validate
예) 사용자가 username을 적는 중에 api에 요청을 보내 이미 있는 username인지 확인하여 알려주기
validate:함수로 값을 가지고 value를 인자로 받아 true와 false를 반환함.
firstName 항목에 nico라는 이름을 갖고 있으면 에러
<input
{...register("firstName", { required: "write here", validate: (value)=> !value.includes("nico")})}
placeholder="firstName"
/>
react-hook-form에서 문자열 반환은 에러메세지를 뜻함. 따라서 다음과 같이 작성가능
<input
{...register("firstName", {
required: "write here",
validate: (value) =>
value.includes("nico") ? "no nicos allowed" : true,
})}
placeholder="firstName"
/>
validate는 함수로 형식을 갖거나, 객체로 여러가지 조건을 갖을 수 도있다.
ansync 로 값을 요청해서 받아서 서버에 체크해 검사도 가능.
validate:{
noNico:(value) =>
value.includes("nico") ? "no nicos allowed" : true,
noNick:(value) =>
value.includes("nick") ? "no nick allowed" : true,
}
https://react-hook-form.com/api/useform/register/
useForm - register
Performant, flexible and extensible forms with easy-to-use validation.
react-hook-form.com
모든 validation은 handlesubmit 호출하면 수행 됨.
onSubmit이벤트에 등록해야함. 인자는 딱 한개를 받는데 바로 onValid 함수 (formdata가 유효할 때 호출되는 함수 .)
const onValid = (data: IForm) => {
if (data.password !== data.password2) {
return setError(
"password",
{ message: "Password are not same" },
{ shouldFocus: true }
);
}
setError("extraError", { message: "Server offline" });
};
return (
<div>
<form
style={{ display: "flex", flexDirection: "column" }}
onSubmit={handleSubmit(onValid)}
>'
11. const{setValue} = useForm();
onSubmit 후 value 비우고싶을 때
간단한 todoList
import React from "react";
import { useForm } from "react-hook-form";
interface IForm {
toDo: string;
}
function ToDoList() {
const {
register,
handleSubmit,
formState: { errors },
setValue,
} = useForm<IForm>();
const handleValid = (data: IForm) => { //form이 유효하면 submit되고
console.log("add to do ", data.toDo);
setValue("toDo", ""); //toDo에 있는 value가 ""로 변경됨
};
return (
<div>
<form onSubmit={handleSubmit(handleValid)}> //
<input
{...register("toDo", {
required: "please write to Do",
})}
placeholder="write a to do"
/>
<button>Add</button>
<span>{errors?.toDo?.message}</span>
</form>
</div>
);
}
export default ToDoList;