본문 바로가기

programming/React

[React Custom Hook] Form 의 required field 확인하는 hook (useFormValidation)

1. Form 의 required field 확인하는 hook

  • input
    • fromRef: 타겟 Form element
    • formDataState : 관리되는 form 데이터 state
    • submitFlag : 제출 버튼 눌렀는지 여부
  • output
    • isFormValidated : validation 통과 되었는지 boolean

 

useFormValidation.ts

  • 코드
import { useEffect, useState } from "react";
// input : formRef, 제출할 formData, submitFlag
// output : 통과 여부

export const useFormValidation = ({ formRef, formDataState, submitFlag }) => {
  const [isFormValidated, setIsFormValidated] = useState(false);

  useEffect(() => {
    if (submitFlag) {
      const inputs = [...formRef.current.elements];
      console.log("inputs", inputs);
      inputs.forEach((el) => {
        // input & select 만 체크 && // required 만 체크
        if (["SELECT", "INPUT", "TEXTAREA"].includes(el.tagName)) {
          if (!el.value && el.required) {
            el.classList.add("is-invalid");
            if (el.parentNode.lastChild.id !== "required-noti-text") {
              const requiredErrorTextDiv = document.createElement("div");
              requiredErrorTextDiv.innerHTML = "Required";
              requiredErrorTextDiv.style.cssText = "color: #E63757; font-size: 10px; margin-top: 0.25rem";
              requiredErrorTextDiv.id = "required-noti-text";
              el.parentNode.appendChild(requiredErrorTextDiv);
            }
          } else {
            el.classList.remove("is-invalid");
            const requiredErrorTextDiv = el.parentNode.querySelector("#required-noti-text");
            if (requiredErrorTextDiv) el.parentNode.removeChild(requiredErrorTextDiv);
          }
        }
      });
      // 성공 여부
      const invalid = document.querySelectorAll(".is-invalid");
      if (invalid.length === 0) setIsFormValidated(true);
    } else {
      // submitFlag false 일때 valid 결과 false 리턴
      setIsFormValidated(false);
    }
  }, [submitFlag, formDataState]);

  return { isFormValidated };
};

 

 

MyComponent.tsx

  • 사용하는 컴포넌트 코드
const [submitFlag, setSubmitFlag] = useState(false);
const formElement = useRef<any>(null);
const [resultData, setResultData] = useState({});

const { isFormValidated } = useFormValidation({
  formRef: formElement,
  formDataState: bannerDetailPutData,
  submitFlag,
});

const onClickSave = () => {
	setSubmitFlag(true);
	if (isFormValidated) {
	  productListPostMutate.mutate(resultData);
	}
}

return (
	<Form ref={formElement}>
		<Button type="button" onClick={onClickSave}>save</Button>
		...
		<Row className="mb-2">
	    <Col md={12} xs={12}>
	      <Form.Control
	        required
	        as="textarea"
	        rows={1}
	        style={{ resize: "none" }}
	        placeholder="Input Meta Title"
	        disabled={pageInfo === "detail" && !editFlag}
	        name="metaTitle"
	        value={el?.metaTitle || ""}
	        onChange={(e) => onChangeDragItem(e, idx)}
	      />
	    </Col>
	  </Row>
		...
	<Form>
)