ref로 외부영역 클릭 감지

togongs·2022년 12월 6일
0

2022

목록 보기
10/19

div 외부 클릭 감지

  • ref 객체인 outsideRef 들과 div 엘리먼트를 연결합니다.
return (
  <FormBox ref={outsideNameRef}>
    ...
    <ErrorMsgBox>{errorMsgName}</ErrorMsgBox>
    ...
  </FormBox>

  <FormBox ref={outsideIdRef}>
    ...
    <ErrorMsgBox>{errorMsgId}</ErrorMsgBox>
    ...
  </FormBox>

  <FormBox ref={outsidePwRef}>
    ...
    <ErrorMsgBox>{errorMsgPw}</ErrorMsgBox>
    ...
  </FormBox>

  <FormBox ref={outsidePwCheckRef}>
    ...
    <ErrorMsgBox>{errorMsgPwCheck}</ErrorMsgBox>
    ...
  </FormBox>
)
  • outsideRef 객체들에 어떠한 값이 변경되었을 때만 실행되는 useEffect() 함수를 작성합니다
 useEffect(() => {
    // 현재 document에서 mousedown 이벤트가 동작하면 호출되는 함수입니다.
    function handleClickOutside(event: any) {
      if (
        outsideNameRef.current &&
        !outsideNameRef.current.contains(event.target)
      ) {
        // console.log('name div 외부 클릭을 감지!');

        const nameValue = inputNameRef.current.value;
        const regex = NAME_REGEX;
        const result = regex.test(nameValue);

        if (nameValue !== '' && !result) {
          setErrorMsgName(ERROR_MSG.invalidName);
        }
      }
      if (
        outsideIdRef.current &&
        !outsideIdRef.current.contains(event.target)
      ) {
        // console.log('id div 외부 클릭을 감지!');
        const idValue = inputIdRef.current.value;
        // setErrorMsgId('');
      }
      if (
        outsidePwRef.current &&
        !outsidePwRef.current.contains(event.target)
      ) {
        // console.log('pw div 외부 클릭을 감지!');
        const pwValue = inputPwRef.current.value;
        const regex = PW_REGEX;
        const result = regex.test(pwValue);
        if (pwValue !== '' && !result) {
          setErrorMsgPw(ERROR_MSG.invalidPw);
        }
      }
      if (
        outsidePwCheckRef.current &&
        !outsidePwCheckRef.current.contains(event.target)
      ) {
        // console.log('pwcheck div 외부 클릭을 감지!');
        let result;
        const pwValue = inputPwRef.current.value;
        let pwCheckValue;
        pwCheckValue = inputPwCheckRef.current.value;
        pwCheckValue = pwCheckValue.replace(pwValue, ''); // pw랑 같은지 비교
        if (pwCheckValue !== '' && !result) {
          setErrorMsgPwCheck(ERROR_MSG.invalidPwCheck);
        } else {
          setErrorMsgPwCheck('');
        }
      }
    }
    document.addEventListener('click', handleClickOutside);
    return () => {
      document.removeEventListener('click', handleClickOutside);
    };
  }, []);
  • document에서 click 이벤트가 동작하면, handleClickOutside 함수가 실행되도록 이벤트 리스너를 추가합니다

최종코드

const outsideNameRef = useRef() as React.MutableRefObject<HTMLInputElement>;
const outsideIdRef = useRef() as React.MutableRefObject<HTMLInputElement>;
const outsidePwRef = useRef() as React.MutableRefObject<HTMLInputElement>;
const outsidePwCheckRef =
      useRef() as React.MutableRefObject<HTMLInputElement>;
const inputNameRef = useRef() as React.MutableRefObject<HTMLInputElement>;
const inputIdRef = useRef() as React.MutableRefObject<HTMLInputElement>;
const inputPwRef = useRef() as React.MutableRefObject<HTMLInputElement>;
const inputPwCheckRef = useRef() as React.MutableRefObject<HTMLInputElement>;


// 외부영역 클릭 감지
  useEffect(() => {
    // 현재 document에서 mousedown 이벤트가 동작하면 호출되는 함수입니다.
    function handleClickOutside(event: any) {
      if (
        outsideNameRef.current &&
        !outsideNameRef.current.contains(event.target)
      ) {
        // console.log('name div 외부 클릭을 감지!');

        const nameValue = inputNameRef.current.value;
        const regex = NAME_REGEX;
        const result = regex.test(nameValue);

        if (nameValue !== '' && !result) {
          setErrorMsgName(ERROR_MSG.invalidName);
        }
      }
      if (
        outsideIdRef.current &&
        !outsideIdRef.current.contains(event.target)
      ) {
        // console.log('id div 외부 클릭을 감지!');
        const idValue = inputIdRef.current.value;
        // setErrorMsgId('');
      }
      if (
        outsidePwRef.current &&
        !outsidePwRef.current.contains(event.target)
      ) {
        // console.log('pw div 외부 클릭을 감지!');
        const pwValue = inputPwRef.current.value;
        const regex = PW_REGEX;
        const result = regex.test(pwValue);
        if (pwValue !== '' && !result) {
          setErrorMsgPw(ERROR_MSG.invalidPw);
        }
      }
      if (
        outsidePwCheckRef.current &&
        !outsidePwCheckRef.current.contains(event.target)
      ) {
        // console.log('pwcheck div 외부 클릭을 감지!');
        let result;
        const pwValue = inputPwRef.current.value;
        let pwCheckValue;
        pwCheckValue = inputPwCheckRef.current.value;
        pwCheckValue = pwCheckValue.replace(pwValue, ''); // pw랑 같은지 비교
        if (pwCheckValue !== '' && !result) {
          setErrorMsgPwCheck(ERROR_MSG.invalidPwCheck);
        } else {
          setErrorMsgPwCheck('');
        }
      }
    }
    document.addEventListener('click', handleClickOutside);
    return () => {
      document.removeEventListener('click', handleClickOutside);
    };
  }, []);

return (
  <FormBox ref={outsideNameRef}>
    ...
    <ErrorMsgBox>{errorMsgName}</ErrorMsgBox>
    ...
  </FormBox>

  <FormBox ref={outsideIdRef}>
    ...
    <ErrorMsgBox>{errorMsgId}</ErrorMsgBox>
    ...
  </FormBox>

  <FormBox ref={outsidePwRef}>
    ...
    <ErrorMsgBox>{errorMsgPw}</ErrorMsgBox>
    ...
  </FormBox>

  <FormBox ref={outsidePwCheckRef}>
    ...
    <ErrorMsgBox>{errorMsgPwCheck}</ErrorMsgBox>
    ...
  </FormBox>
)

참고 블로그

profile
개발기록

0개의 댓글