학원 수업 Day20

validation

리액트 버전의 validation 을 제작했다.


초기값 세팅

에러 체크를 위해 각 inputvalue 값을 저장해야한다.

폼 초기값 객체를 기본값으로 하는 state 로 생성한다.

const initVal = {
  userId: '',
  email: '',
  pwd1: '',
  pwd2: '',
  gender: null,
  interests: null,
  edu: '',
  comments: '',
};
const [ val, setVal ] = useState(initVal);

그리고 에러 메세지와 validation 통과 후 true 값으로 전환하기 위한 state 도 생성해준다.

const [ err, setErr ] = useState({});
const [ submit, setSubmit ] = useState(false);


value값 객체에 할당

const handleChange = (e) => {
  // input[type=text] 시 value값 객체에 할당
  const { name, value } = e.target;
  setVal({...val, [name]: value});
}

const handleRadio = (e) => {
  // input[type=radio] 선택 시 true값 할당
  const { name } = e.target;
  const isChecked = e.target.checked;
  setVal({...val, [name]: isChecked});
}

const handleCheck = (e) => {
  // input[type=checkbox] 체크 시 true값, 체크 아웃 시 false 할당
  // 생각해보니 라디오도 그냥 이걸 쓰면 되지 않을까?
  const { name } = e.target;
  let isChecked = false;
  isChecked = e.target.checked ? true : false;
  setVal({...val, [name]: isChecked});
}

const handleSelect = (e) => {
  // select 선택 시 value값 객체에 할당
  const { name } = e.target;
  const isSelected = e.target.value;
  setVal({...val, [name]: isSelected});
}

주의할 점 : key 값을 변수로 지정할때 대괄호로 묶는다.


값 체크

값을 받아 에러 메세지를 담은 객체를 리턴한다.

const checkVal = (value) => {
  const errs = {};

  if (value.userId.length < 5) {
    // input[type=text] 길이 확인
    errs.userId = '아이디를 5글자 이상 입력하세요.';
  }

  if (value.email.length < 8 || !/@/.test(value.email)) {
    errs.email = '이메일 형식에 맞게 8글자 이상 입력하세요.';
  }

  const testPwd = (val) => {
    const errType = [];
    // 에러 메세지 담을 빈배열 생성
    const reg = {
      '영문자': /[a-zA-z]/,
      '숫자': /[0-9]/,
      '특수문자': /[!@#$%^&*()_+]/,
    }
    // 에러 조건 정규식 지정
    if (val.length < 8) errType.push('8글자 이상');
    for (const curKey of Object.keys(reg)) {
      if (!reg[curKey].test(val)) errType.push(curKey);
    }
    // 에러 상황 발생시 메세지를 배열에 추가
    return errType.join(', ');
    // 에러 배열 합쳐서 문자열로 반환
  }
  if (testPwd(value.pwd1)) {
    // input[type=password] 조건이 길어서 별도 함수 처리
    errs.pwd1 = '형식에 맞게 입력하세요. (' + testPwd(value.pwd1) + ')';
  }

  if (value.pwd2 < 3 || value.pwd1 !== value.pwd2) {
    errs.pwd2 = '비밀번호를 동일하게 입력하세요.';
  }

  if (!value.gender) {
    // input[type=radio] 선택 여부 확인
    errs.gender = '성별을 선택하세요.';
  }

  // 기타 등등...
}

submit 이벤트로 객체에 저장된 값들을 체크해서 반환되는 에러 메세지를 객체로 넣어준다.

const handleSubmit = (e) => {
  e.preventDefault();
  setErr(checkVal(val));
  setSubmit(true);
}

마지막으로 submittrue 값을 넣어준다.

useEffect(() => {
  const len = Object.keys(err).length;
  if (!len && submit) {
    alert('회원 가입이 완료되었습니다. 메인 페이지로 이동합니다');
    history.push('/youtube');
  };
}, [])

에러 메세지 객체가 비어있고 submit 상태가 true 라면 성공 메세지를 띄우고 페이지를 이동시킨다.

지금은 만들어진 페이지가 youtube 페이지 밖에 없다…..


JSX 부분

<input type="text"
  placeholder='아이디를 입력하세요'
  name="userId" id="userId"
  value={val.userId}
  onChange={handleChange}
/>
{err.userId && <span className='err'>{err.userId}</span>}

inputvalue 에 저장된 객체 내의 값을 적용시킴과 동시에 onChange 이벤트로 객체 내에 할당해줘서 실시간으로 이어서 수정될 수 있도록 한다.

에러 객체 내 해당하는 에러 메세지가 있다면 에러 메세지를 표시한다.


reset 버튼

<button type='reset' onClick={handleReset}>RESET</button>
const handleReset = () => {
  setVal(initVal);
  setErr({});
  setSubmit(false);
}

기존에 저장되었던 state 를 모두 초기값으로 돌려준다.


useHistory()

import { useHistory } from 'react-router-dom';

const history = useHistory();

URL 주소를 변경할 때 사용하는 Hook으로, 리액트는 url변경 없이 컴포넌트만 변경시킬 수 있지만 useHistory() 로 url 주소를 변경해서 사용자가 인식하도록 할 수 있다.

사용자 친화적 페이지 구축에 필요하다.

  • Router v5 : useHistory()

  • Router v6 : useNavigate()

라우터 버전이 올라가면서 해당 기능을 하는 Hook의 이름이 바뀌었다고 한다.


나머지 시간은 자습시간이었다.

청약닷컴 리액트 버전 제작중!