본문 바로가기
ReactJS

React-hook-form with Material UI

by CARD_JOKER 2020. 6. 2.
import { useForm } from 'react-hook-form'
const { register, handleSubmit, errors, setValue } = useForm()

 

register

required/max/min/maxLength/minLength/pattern/validate 등 validation 값 지정 하는 용도

handleSubmit

submit handler ( react에선 return false가 이루어 지지 않는다 그래서 react-hook-form에서 별도로 제공하는 submit 핸들 함수 이다.

errors

각 input의 에러를 핸들 하고 있는 변수 이다.

setValue

input만 사용한다면 필요 없지만 checkBox나 select 등 control component에서 사용 해야 하는 변수다

 

들어가기에 앞서 위의 react-hook-form 을 npm install 해주셔야 합니다.

 


Material UI with React Hook Form

Type1. input text

<FormControl error={Boolean(errors.userName)} fullWidth={true}>
     <InputLabel htmlFor="component-nm">User Name</InputLabel>
          <Input
              id="component-nm"
              inputRef={register({ required: true })}
              name="userName"
              />
           <FormHelperText> 
           	{errors.userName && <span>사용자 명은 필수 입니다.</span>} 
           </FormHelperText>
</FormControl>

위 코드에서 error에 Boolean을 지정해 준 이유는 객체로 받을 경우가 있어 꼭 Boolean으로 반환하여 달라는 ERROR로 인해 boolean으로 캐스팅 하였다.

저기서 봐야할 것은 inputRef={register({required: true})} 이다

원래 일반 <input type="text" 태그는 ref 만 사용한다. 허나 Material UI와 같은 UI library와 같이 사용하려면 inputRef를 사용 하라고 기재 되어있다.

그리고 또 중요한 코드는 name 입니다. react-hook-form*은 input의 name값으로 *ref 하여 생성 되므로 name이 무조건 있어야 하며 추후 반환되는 data도 name값으로 반환 됩니다. 또한 Control Component에서 중요한 역활을 합니다.




여러 validation 적용 방법 두가지

1. Register 내 속성 여럿 선언 후 Error type별로 에러메세지 출력

<FormControl error={Boolean(errors.numberIn)} fullWidth={true}>
   <InputLabel htmlFor="component-no">숫자입력</InputLabel>
        <Input
           id="component-no"
           inputRef={register({ 
                    	required: true, 
                        minLength: 13, 
                        maxLength: 13, 
                        pattern: /^[0-9]+$/ })}
           name="numberIn"
           />
    <FormHelperText> 
         {errors.numberIn 
         	&& errors.numberIn.type === 'required' 
            	&& <span>숫자입력란은 필수 입니다.</span>} 
         {errors.numberIn 
         	&& errors.numberIn.type === 'minLength' 
            	&&  <span>숫자입력란은 최소 13자리 입니다.</span>} 
         {errors.numberIn 
         	&& errors.numberIn.type === 'maxLength' 
            	&&  <span>숫자입력란은 최대 13자리 입니다.</span>}
         {errors.numberIn 
         	&& errors.numberIn.type === 'pattern' 
            	&& <span>숫자입력란은 숫자만 가능합니다.</span> } 
     </FormHelperText>
</FormControl>

 

2. message 형식을 inputRef 내에 지정

...
import { useForm, ErrorMessage  } from 'react-hook-form' //ErrorMessage 추가
...

<FormControl error={Boolean(errors.numberIn)} fullWidth={true}>
    <InputLabel htmlFor="component-no">숫자입력</InputLabel>
           <Input
              id="component-no"
              inputRef={register({ 
                  required: '숫자입력란은 필수 입니다', 
                  minLength: {
                      value: 13,
                      message: '숫자입력란은 최소 13자리 입니다.'
                  }, 
                  maxLength: {
                      value: 13,
                      message: '숫자입력란은 최대 13자리 입니다.'
                  }, 
                  pattern: {
                       value : /^[0-9]+$/,
                       message: '숫자입력란은 숫자만 가능합니다.'
                  }
              })}
              name="numberIn"
              />
      <ErrorMessage errors={errors} name="numberIn">
           {({ message }) => <FormHelperText>{message}</FormHelperText>}
     </ErrorMessage>
</FormControl>

그외 API는 링크를 참조 하세요 :link: https://react-hook-form.com/kr/api#register

함수를 통한 아이디 중복 확인 같은 boolean을 return 해주는 validate 도 가능합니다.
위 사이트에서 validate 객체를 참고해주세요.


Type2. Control Component에 적용하기

첫번째, 일반 component를 생성합니다.

 <FormControl error={Boolean(errors.usrAuth && !isSelected)} fullWidth={true}>
     <InputLabel id="demo-simple-select-label">권한</InputLabel>
           <Select
               labelId="demo-simple-select-label"
               id="demo-simple-select"
               name="usrAuth"
               value = {value}
               onChange = {(e) => handleChange(e)}
               >
                 <MenuItem value={10}>관리자</MenuItem>
                 <MenuItem value={20}>중간관리자</MenuItem>
                 <MenuItem value={30}>사용자</MenuItem>
             </Select>
    {errors.usrAuth 
    	&& !isSelected 
        	&& <FormHelperText> Select Box 연동 테스트</FormHelperText>}
</FormControl>
  1. 생성 시 nameref로 사용되므로 아무거나 주어도 상관 없지만 알고 있어야 합니다.
  2. value 는 Material에서 value값이 없으면 Error가 나므로 바인딩 해주었습니다. [ value, setSelectValue ] (중요도 낮음 근데 알고 있어야 함)
  3. handleChange  함수는 바로 뒤에 설명 드리 도록 하겠습니다.
  4. control component의 경우는 Text input 과 다르게 바로 Error Message가 바인딩 되지 않고 submit 시 에러 체크 가 되므로 <FormControl error = {Boolean(errors.usrAuth&& !isSelected)} 를 통해 바로 error 유무가 처리 되도록 하였습니다.

 

두번째 이자 마지막, handleChangeuseEffect에서 register선언

useEffect(() => {
    register({ name:"usrAuth"}, {required: true})
},[register])

const [ value, setSelectValue ] = useState('')
const [ isSelected , setIsSelected ] = useState(false)

const handleChange = (e) => {
    setIsSelected(true)
    setSelectValue(e.target.value)
    setValue("center",e.target.value)
}
  1. setIsSelected = FormControl의 Error 핸들 용 ( 중요도 보통 )
  2. setSelectValue = Materail UI의 no value Error를 위한 용도 ( 중요도 보통 )
  3. setValue = **매우중요** setValue(<register에서 선언한 이름>, <값>) 을 통해 값을 react-hook-form 과 바인딩 시킨다.

 

이건 UI상 CheckBox 선언 형식 권장

 

<FormControl error={Boolean(errors.ppchk && !isPPchk)} fullWidth={true} >
     <FormLabel>
          <Checkbox 
            color="secondary" 
            name="ppchk" 
            onChange = {() => handlePPchk()} />
           개인 정보 처리 방침
           {errors.ppchk && !isPPchk && <span> ( 동의 후 가입 가능합니다 ) </span>}
     </FormLabel>
</FormControl>



댓글