포커스 아웃시 유효성 검사
- 요즘의 웹서비스들은 따로 중복검사 버튼을 누르지 않아도 유저의 포커스 아웃(기입칸외의 다른 곳을 클릭)시 유효성 검사를 하게 되어있다.(과거에도 많이 그랬다면.. 할 말은 없다)
- 이것을 구현하려면 기본적으로 input 태그의 onBlur속성을 알아야 한다.
onBlur
- onFocus가 input창이 포커스되었을 때 호출할 함수를 사용한다면
- onBlur는 input창이 포커스아웃되었을 때 호출할 함수를 사용한다.
<input
ref={idRef}
type="id"
value={id}
onChange={onChangeId}
placeholder="이메일을 입력해 주세요"
onBlur={onClickIdDup}
data-testid="idInput"
/>
- 이런식으로 사용한다면 포커스아웃 될때마다 onClickIdDup이라는 함수를 호출하며 유효성 검사를 할 수 있다.
const onClickIdDup = useCallback(
e => {
e.preventDefault();
if (!id.trim()) {
setIdTrim(true);
return;
}
setIdTrim(false);
idChecker();
dispatch(__duplicate_check(id));
setIdDupCheck(true);
if (!id.trim()) {
setIdNotice(true);
return;
}
setIdNotice(false);
},
[dispatch, id, idChecker],
);
- 앞서 설명했던 useCallback을 다시 여기서 설명하자면
- 의존성 배열에 dispatch, id, idChecker가 들어가 있다.
- 그 이유는 이 onClickIdDup 함수가 dispatch, id, idChecker의 값이 변할때마다
- 이 함수를 재생성해야 하기 때문이다.
- 역으로 생각해보면 이 함수는 dispatch와 id, idChecker의 값에 의존하고 있다는 뜻인데 어떻게 그런것인지 하나씩 풀어나가보자.
- https://narup.tistory.com/220
공백을 확인하는 법
- 회원가입에서 유효성을 검사할 때 제일 먼저 하는 것은 유저가 공백으로 넘어가지는 않았나 하는 점이다.
- 여기서 사용되는 함수는 trim() 이다.
- trim은 문자열 앞 뒤의 공백을 없애주는 함수인데 이게 앞에! 가 붙는다면 공백이거나 블랭크만 있을경우 true를 반환하게 된다.
- const [idTrim, setIdTrim] = useState(false); 이렇게 설정하면
- idTrim이 true일 경우 유저가 기입하지 않았거나 블랭크로 넣었다는 것을 알 수 있다.
- 이후에는 return을 넣어줘 굳이 코드들을 실행시키지 않는다.
- {idTrim && !id && <span>필수 입력 정보입니다</span>} 이후 input창 밑에 에러메시지를 이렇게 설정해 주면 공백확인이 끝이 난다.
- 여기서 idTrim 과 !id를 같이 넣어준 이유는
- idTrim만 넣어주게 되면 처음에 유저가 클릭하고 빈칸으로 넘어갔을때는 잡지만 실시간으로 onChange되며 유저가 값을 넣었을 때는 잡지 못하기 때문이며
- 반대로 !id(!id는 값이 넣어있지 않다면 true가 된다.)는 기입할 경우 에러가 해제 되지만 처음부터 계속 에러로 표시 되기 때문에 상호보완적인 관계이다.
정규식 이용
- 공백을 넘었다면 onBlur함수 내에서 setIdTrim(false); 를 해줌으로써 확실하게 공백에러를 넘어가 준다.
- 이후 idChecker로 넘어간다.
const idChecker = useCallback(() => {
if (!id.trim()) {
setIdError(true);
setIdNotice(true);
return false;
}
if (!idFilter(id)) {
setIdError(true);
setIdNotice(true);
return false;
}
setIdError(false);
return true;
}, [idFilter, id]);
- idChecker 또한 useCallback으로 감싸져 있는데 이는 idFilter와 id값에만 의존하는 함수이며, 다른 상황에는 리렌더링 하지 않는다는 뜻이다.
- 우선 다시금 공백을 확인해준다.
- 이후 만약 공백이라면 ex) 유저가 썼다가 다시 지운 경우 error와 notice를 true로 해준다.
- error의 경우 원래 false이지만 notice의 경우는 원래 true였다.
- 이 notice값은 우선 회원가입의 경우 만약 아래 에러메시지 칸에 무언가 쓰여져 있게 하고 싶을 때 쓰는 것이며 에러가 나면 유저가 다시 값을 다 지웠을 때 에러를 없애기 위해 true로 바꾸는 것이다.
- 다만 나의 경우 처음 시작할 때 안내메시지가 에러메시지 칸에 나오지 않으므로 거의 기능을 상실했고 조만간 리팩토링을 한다면 지워야 한다.
const idFilter = useCallback(id => {
const filter = /[a-z0-9]+@[a-z]+\.[a-z]{2,3}/;
return filter.test(id);
}, []);
- 이후 idFilter로 유효성 검사를 해주는 데 이때 정규식이 이용된다.
- 정규식에 관한 내용은 https://velog.io/@moolbum/JavaScript-정규표현식
- 여기가 좋다.
- 여기서도 useCallback을 사용하는데 의존하는 state가 없으므로 빈 배열로 두었다(id는 가져와서 변경하기만 할뿐 id가 바뀐다 해서 idFilter함수가 리렌더링 될 필요가 없다.)
- 이후 정규식의 test메서드를 통해 검사를 하고 에러라면 idError를 true로 바꿔준다.
- 여기서 idFilter값을 그대로 사용하지 않는 이유는 함수 하나에서 공백과 유효성을 검사하고 이를 하나의 에러로 보낼 것이기 때문이다.
- (함수의 추상화? 모듈화? 클린코드와 관련된 리팩토링 부분 같은데 나중에 기회가 된다면 리팩토링에 대해 공부해보고 싶다.)
- 이후 정규식을 통과하면 idError의 값을 false로 바꿔준다.
- idFilter에서 사용되는 state는 idFilter와 id만이므로 useCallback의 의존성배열에는 두 값만 들어간다.
- 그 다음에는 중복을 검사한다.
레퍼런스 주소
https://itchallenger.tistory.com/258
https://velog.io/@ashnamuh/React의-useReducer-useCallback-useMemo-제대로-알고-사용하기
https://www.daleseo.com/react-hooks-use-callback/
https://velog.io/@moolbum/JavaScript-정규표현식
https://kkk-kkk.tistory.com/entry/예제-9-16-onfocus와-onblur-이름을-입력하지-않고-다른-창으로-갈-수-없음
https://velog.io/@niboo/React-onFocus-와-onBlur이벤트를-사용하여-인풋창-색상-변경하기
'develop' 카테고리의 다른 글
props in styled-componenets, 템플릿 리터럴, 조건부 렌더링 (2) | 2023.01.20 |
---|---|
react로 회원가입(3)-중복검사, 조건부 렌더링, 에러시 포커스이동 (0) | 2023.01.20 |
react로 회원가입(1)-커스텀훅,구조분해할당,useCallback (0) | 2023.01.20 |
호스팅 업체와 FTP와 cors.. (0) | 2023.01.20 |
termius 와 remote -ssh 와 ssh 프로토콜 (0) | 2023.01.20 |