useForm에서 체크박스 체크 여부에 따른 버튼 활성화 기능 구현하기

blueprint·2023년 3월 23일
0
post-thumbnail

useForm을 이용해서 주문서 폼을 만들던 도중 한 문제에 직면하게 됐다.
위의 폼에서 체크박스를 체크해야 결제하기 버튼이 초록색으로 바뀌며 활성화되도록 하고 싶었다. useState를 이용해 체크박스의 상태를 컨트롤하려고 했으나 state가 많아지면 리렌더링이 계속된다는 단점이 있어 useForm으로 폼을 만들고 있었기 때문에 useForm 안의 기능들로 해결하고 싶었다.

우선 마크업은 이렇다.

<input type="checkbox" id="check" {...register("checkBox", { required: true })}
/>
<label htmlFor="check"> 주문 내용을 확인하였으며, 정보 제공 등에 동의합니다.</label>

useForm에는 폼의 상태를 알 수 있는 formState가 있다. 이 안에는 isValid라는 에러가 있는지 확인해 주는 친구가 있다. isValid를 사용해 체크박스를 동작시켜 보았다.

const {
	register,
    formState: { errors, isValid },
    handleSubmit,
  } = useForm({
    mode: "onBlur",
  });

mode가 onBlur인 상태라 바깥 부분을 한 번 눌러 줘야 값이 변경된다는 점과, false만 출력하는 절망적인 결과를 보게 되었다. 알고 보니 isValid는 렌더링 이후에 유효성 검사를 한다는 문제점이 있다는 것. 그래서 이 함수를 커스텀(?) 해 보기로 했다.

입력되는 값을 실시간으로 감시하기 위해서 watch 함수를 사용한다. watch 함수는 폼에 입력된 값을 실시간으로 체크한다. 그런 다음 isValid에 담아 콘솔에 찍어 보면 다음과 같은 결과를 얻을 수 있다.

const {
	register,
    formState: { errors },
    handleSubmit,
    watch,
} = useForm({
	mode: "onBlur",
});

const isValid = watch("checkBox");

체크박스는 초깃값이 null인 상태. 이 상태를 체크 전과 체크 후로 나눠 감시하기 위해 초깃값(체크되지 않은 상태)을 false로, 체크된 상태를 true로 출력할 수 있게 다음처럼 바꿔 주었다.

const {
	register,
    formState: { errors },
    handleSubmit,
    watch,
} = useForm({
	mode: "onBlur",
	defaultValues: { checkBox: false },
});

const isValid = watch("checkBox");

그런 다음 disabled 속성에 !isValid를 입력해 준다. true 값이 들어갈 때 disabled 속성이 동작되도록 해야 하기 때문이다.

  • 체크박스 false - disabled true - 버튼 비활성화
  • 체크박스 true - disabled false - 버튼 활성화
<button disabled={!isValid} onClick={onSubmit}>결제하기</button>

🔗 참고
formState.isValid return true in initial render with mode onChange,onBlur #1512

0개의 댓글