리액트에는 텍스트 필드(input 태그로) 입력시 state로 컴포넌트의 상태값을 관리합니다.
const [text, setText] = useState('')
const handleText = (e) => {
e.preventDefault();
// sumbit 이벤트 발생시 페이지 새로고침 현상 방지
console.log('제출 버튼 클릭');
}
return(
<form onSubmit={handleText}>
<input value={text} onChange={(e) => setText(e.target.value)}/>
<button>제출</button>
</form>
)
위와 같이 리액트에서 값을 관리하는 폼 요소를 제어 컴포넌트라고 합니다.
하지만 상태값이 변경될때마다 컴포넌트가 매번 렌더링되는 이슈가 발생합니다. 이를 방지하기 위해서
비제어 방식의 react-hook-form 라이브러리를 활용하여 폼을 관리할 수 있고 유효성 체크를 진행할 수 있습니다.
register 함수는 useForm 함수에서 가져와 사용할 수 있습니다.
const {register, handleSubmit} = useForm<any>({mode : "onChange"});
const phoneSubmit = async (data : any) => {
console.log(data)
/*
{
phone : '0101234567'
}
*/
}
return(
<form onSubmit={handleSubmit(phoneSubmit)}>
<input {...register("phone")}/>
<button>제출</button>
</form>
)
/*
<input {...register('firstName')} />는 아래와 동일한 의미
<input
onChange={onChange}
onBlur={onBlur}
name={name}
ref={ref}
/>
*/
mode : onChange 이벤트 사용 : 입력할때마다 유효성 체크 => 유효성 만족 안할 경우 에러 메시지 출력
required : 해당 필드가 유효성을 만족해야 최종적으로 inValid가 true로 적용.
patten : value 유효성 만족 조건을 정규식으로 작성, message에 유효성을 만족하지 않을 경우 표시할 에러 메시지 정의
import { styled } from "styled-components"
import { useForm } from "react-hook-form"
export default function Password(){
const regexSpecialSign = /[{}[\]\/?.,;:|)*~`!^_+<>@#$%&\\=('""]/g; // 특수문자
const {register, handleSubmit, watch, formState : {isValid, errors}} = useForm<any>({mode : "onChange"});
const changePwordSubmit = async (data : any) => {
const body = {
...data,
param1 : sessionStorage.getItem("param1")
}
// 이곳에 API 호출 로직 작성
return(
<form onSubmit={handleSubmit(changePwordSubmit)}>
<div>
<h4>변경 패스워드</h4>
<input type ="password"
style={{width : '300px', borderRadius : '10px'}}
placeholder={'영문자, 숫자 포함 6자 이상 12자 이하 사용'}
{...register('new_pw', {
required : true,
pattern : {
value : /^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d]{6,12}$/,
message : '잘못된 패스워드 입니다.'
},
onChange: (e) => {
const value = e.target.value;
const sanitizedValue = value.replace(regexSpecialSign, ''); // 패턴에 일치하는 문자열을 제거
e.target.value = sanitizedValue; // 제거된 값을 다시 입력란에 할당
},
})}
/>
<p>{errors.new_pw && <span>{errors.new_pw.message}</span>}
</p>
<button
disabled={!isValid}
style={{backgroundColor : isValid ? 'red' : 'gray'}}>
</button>
</div>
</form>