설치하고 import 해준다.
import { useForm } from "react-hook-form";
import { DevTool } from '@hookform/devtools'
유효성 판별 결과를 편하게 확인할 수 있는 DevTool도 함께 설치해줬다.
useForm 의 내장함수들 아래처럼 선언해준다. 사용할 것들만 해줘도 된다. (control은 DevTool용)
const {
register
, control
, watch
, handleSubmit
, reset
, setValue
, getValues
, setError
, setFocus
, clearErrors
, trigger
, formState: { errors, isSubmitting, isDirty, dirtyFields, }
} = useForm({
mode: 'onBlur' ,
defaultValues: {
userId: ''
, userPwd: ''
} ,
});
mode는 유효성 검사 판별 시점이고, defaultValues 에 판별할 변수들을 지정해준다.
* mode 옵션
- onBlur : input창에서 focus out 되는 시점.
- onChange : input창 입력값이 변하는 시점.
- onSubmit : form이 제출되는 시점.
회원가입_ 입력창 유효성 검사
<InputItem>
<label htmlFor='userId'>아이디</label>
<input
type="text"
name="userId"
placeholder="아이디"
{...register("userId", {
required: '아이디는 필수입니다.',
pattern: {
value: /^[A-za-z0-9]{5,8}$/ ,
message: '영문+숫자 최대 5~8자'
}
})
}
></input>
</InputItem>
<Err>{errors.userId && <p>{errors.userId.message}</p>}</Err>
[ register 함수의 옵션들 ]
register 함수의 첫번째 인자를 input의 name으로 지정해서 연결
* required (입력값 유무 판별_필수입력값)
위는 required 를 축약형으로 작성한거고,
아래처럼 객체 형태로도 가능 (value값에 변수를 넣어 동적으로 할당 가능)
required: {
value: true,
message: "입력 필수!"
},
* pattern (입력값 정규식 판별)
pattern: {
value: /^[A-Za-z]+$/,
message: "문자만 입력!"
}
* validate (사용자 정의 유효성 검사)
원하는 판별조건을 함수로 지정할 수 있다. (OR 연산자_ 앞부분이 거짓이라면 뒷부분 출력)
validate: {
positiveNumber: value => parseFloat(value) > 0 || "양수만 입력!",
lessThanTen: value => parseInt(value, 10) < 10 || "10이하만 입력!"
}
이건 아래 비밀번호 확인 창에서 활용했다.
회원가입_ 비밀번호 일치여부 검사
<InputItem>
<label htmlFor='userPwd'>비밀번호</label>
<input
type="text"
name="userPwd"
placeholder="비밀번호"
{...register("userPwd", {
required: {
value: true,
message: "비밀번호를 입력해주세요"
},
pattern: {
value: /^[A-za-z0-9]{5,8}$/ ,
message: '영문+숫자 최대 5~8자'
}
})
}
></input>
</InputItem>
<Err>{errors.userPwd && <p>{errors.userPwd.message}</p>}</Err>
<InputItem>
<label htmlFor='userPwdChk'>비밀번호 확인</label>
<input
type="text"
name="userPwdChk"
placeholder="비밀번호 확인"
{...register("userPwdChk", {
required: {
value: true,
message: "비밀번호를 한번더 입력해주세요"
},
validate: {
matchPwd: (value) =>
value === userPwd || "일치하지 않습니다."
}
})
}
></input>
</InputItem>
<Err>{errors.userPwdChk && <p>{errors.userPwdChk.message}</p>}</Err>
* watch
form 내부 필드의 변경을 감지하여 변경값을 가져온다. (해당 필드의 값이 변경될 때마다 컴포넌트가 리렌더링)
* getValues
호출 시점의 해당 필드의 값을 가져온다. (form의 현재 상태만 읽기 때문에 렌더링X)
비밀번호 확인창의 validate 부분은 사용자 지정 함수로 넣어줬다.
validate: {
matchPwd: (value) =>
value === userPwd || "일치하지 않습니다."
}
const userPwd = watch("userPwd");
비밀번호 필드부분 watch 함수로 잡아왔는데 getValues로 해도 될듯 하다...?
validate: {
matchPwd: (value) =>
value === getValues("userPwd") || "일치하지 않습니다."
}
회원가입_ 이용약관 동의 (필수 & 선택)
<TermsItem>
<label htmlFor='allYn'>
<input
type="checkbox"
name="allYn"
id="allYn"
{...register("allYn", {
required: {
valueAsBoolean: true
}
})
}
>
</input>
전체동의</label>
</TermsItem>
<TermsItem>
<label htmlFor='termsYn'>
<input
type="checkbox"
name="termsYn"
id="termsYn"
{...register("termsYn", {
required: {
valueAsBoolean: true
}
})
}
>
</input>
필수동의</label>
</TermsItem>
<TermsItem>
<label htmlFor='optionYn'>
<input
type="checkbox"
name="optionYn"
id="optionYn"
{...register("optionYn", {
required: {
valueAsBoolean: false
}
})
}
>
</input>
선택동의</label>
</TermsItem>
<Err>{errors.termsYn && <p>{errors.termsYn.message}</p>}</Err>
전체동의, 필수동의, 선택동의 세 개의 체크박스가 있고,
'전체동의' 체크/해제시 '필수동의'&'선택동의' 체크박스도 함께 체크/해제되도록 설정.
const allYn = watch("allYn");
이건 변경상태를 감지해서 값을 가져와야 하니 watch를 사용.
useEffect(() => {
setValue("termsYn", allYn? true : false);
setValue("optionYn", allYn? true : false);
},[allYn])
'전체동의' 의 체크박스 값이 변경되면 '필수동의'&'선택동의' 체크박스도 함께 변경된다.
회원가입_ 아이디 중복검사
<InputItem>
<label htmlFor='userId'>아이디</label>
<input
type="text"
name="userId"
placeholder="아이디"
{...register("userId", {
required: {
value: true,
message: "아이디 입력은 필수입니다."
},
pattern: {
value: /^[A-za-z0-9]{5,8}$/ ,
message: '영문+숫자 최대 5~8자'
}
})
}
></input>
</InputItem>
<Err>{errors.userId && <p>{errors.userId.message}</p>}</Err>
<button onClick={(e) =>
checkId(e, getValues("userId"))}>확인</button>
아이디 input창 옆에 button을 만들어주고 클릭이벤트(checkId) 생성. (인자로 이벤트와 아이디값을 가져간다.)
// id중복확인 검사.
const checkId = async (e, id) => {
e.preventDefault();
const isValidId = await trigger("userId");
if(!isValidId){
console.log("유효성검사 실시")
return;
}
//서버로 보내 중복여부 확인하는 로직
console.log("입력한ID : ", id)
}
id 중복확인 버튼을 눌렀을때
e.preventDefault() 로 막아주지 않으면 form 제출 이벤트가 실행되어
전체 필드에 대한 유효성 검사가 실시된다. (모든 에러 메시지가 뜬다.)
이후 trigger를 활용해 id필드에 대한 유효성 검사만 실시 **
( useForm의 mode가 onblur이기 때문에 아이디 input창을 활성화 시키지 않으면 유효성 검사가 실행되지 않는다.
input창 활성화 없이 버튼을 눌렀을 때 유효성 검사가 실행되도록 수동으로 설정해준거다. )
유효성 검사 devtool에서 input창 활성화 여부 및 유효성검사 결과를 확인할 수 있는데
isdirty는 defaultValue와의 값 비교결과여서 다른 정규식에 대해서는 검증이 안된다.
(빈칸일 때)
(정규식에 맞지 않을 때)
이때도 true값이 나온다.
* handleSubmit
form을 제출을 위해 useForm에서 제공하는 함수로, 자동으로 유효성 검사 실행 후 form의 데이터를 전달한다.
아래 두 개의 콜백 함수를 인자로 받음.
- onSubmit : 유효성 검사 성공 시 제출.
- onError : 유효성 검사 실패 시 실행.
return (
<>
<h2>Test</h2>
<Container>
<form onSubmit={handleSubmit(onSubmit, onError)}>
<InputItem>
<label htmlFor='userId'>아이디</label>
<input
type="text"
name="userId"
placeholder="아이디"
{...register("userId", {
required: {
value: true,
message: "아이디 입력은 필수입니다."
},
pattern: {
value: /^[A-za-z0-9]{5,8}$/ ,
message: '영문+숫자 최대 5~8자'
}
})
}
></input>
</InputItem>
<Err>{errors.userId && <p>{errors.userId.message}</p>}</Err>
<InputItem>
....
</InputItem>
....
<button type="submit">제출</button>
</form>
<DevTool control={control} />
</Container>
</>
);
}
각각의 결과를 출력해보면
성공 시 onSubmit
const onSubmit = (data) => {
console.log("data: ", data);
}
// 출력결과
// data: {userId: '입력한ID', ..... , userName: '입력한이름'}
실패 시 onError
const onError = (error) => {
console.log("error: ", error);
}
error:
{userId: {…}}
userId: {type: 'pattern', message: '영문+숫자 최대 5~8자', ref: input}
[[Prototype]]: Object
'React > 공부공부' 카테고리의 다른 글
[ React / ag-grid ] 관련정리 (0) | 2024.05.25 |
---|---|
[React 참고] eslint-disable / Lint 끄기 (WARNING) (0) | 2024.05.25 |
[React Hook] useState (0) | 2024.05.18 |
[React Hook] useRef (0) | 2024.04.14 |
[React Hook] useEffect (0) | 2024.04.13 |