https://rateye.tistory.com/468
유효성 검사하는 거.. 이걸 onChange 함수로 체크해 바로바로 보여줄 수 있는 방식, 중복확인과 가입하기 때 다 체크해줘야 하는데 좋은 방법이 떠오르지 않아서 며칠을 조금씩 수정했는데
함수를 하나 만들어서 value가 바뀔 때마다 확인하고 문구를 보여주려고 했는데 각각의 input 등을 반복문으로 돌려서 inputState value가 한 글자가 바뀔 때마다 validation 함수가 5번씩 호출됐다. 당연한 결과겠지만 바로바로 정규식을 검사할 수 있는 방법이 이것밖에 떠오르지 않았다ㅜㅜ
components/register/SignUp.tsx
function SignUp() {
...
const validation = (name: string) => {
console.log('validation');
const idRegExp = /^[a-z]+[a-z0-9]{5,19}$/g;
const pwRegExp = /^(?=.*\d)(?=.*[a-zA-Z])[0-9a-zA-Z]{8,16}$/;
switch (name) {
case 'id':
return id.value
? idRegExp.test(id.value)
? ''
: '영문자로 시작하는 영문자 또는 숫자 6~20자 '
: '';
case 'pw':
return pw.value
? pwRegExp.test(pw.value)
? ''
: '8 ~ 16자 영문, 숫자 조합'
: '';
case 'pwCheck':
return pwCheck.value
? pw.value === pwCheck.value
? ''
: '비밀번호가 일치하지 않습니다.'
: '';
default:
return '';
}
};
return (
<form onSubmit={handleSignUp}>
{signupInputsData.map(([id, type, title, placeholder]) => (
<>
...
<p className="text-red-400">{validation(id)}</p>
</>
)}
</form>
);
}
아이디나 닉네임 중복 확인을 할 때 체크
...
const signupInputsData = [
['id', 'text', '아이디', '아이디를 입력해주세요.'],
['nickname', 'text', '닉네임', '사용하실 닉네임을 입력해주세요.'],
['pw', 'password', '비밀번호', '비밀번호를 입력해주세요.'],
['pwCheck', 'password', '비밀번호 확인', '비밀번호를 확인합니다.'],
['profileImage', 'text', '프로필 사진', '선택된 파일 없음'],
];
//
function SignUp() {
const [_, setCurrentUser] = useRecoilState(currentUserState);
const [signupInputs, setSignupInputs] = useState<SignupInputs>({
id: { value: '', error: '' },
nickname: { value: '', error: '' },
pw: { value: '', error: '' },
pwCheck: { value: '', error: '' },
profileImage: { value: '', error: '' },
});
const { id, nickname, pw, pwCheck, profileImage } = signupInputs;
const { value: duplicateCheckedId, setValue: setDuplicateCheckedId } =
useInput('');
const {
value: duplicateCheckedNickname,
setValue: setDuplicateCheckedNickname,
} = useInput('');
const { value: fileDataUrl, setValue: setFileDataUrl } = useInput('');
const setSignupInputsValueOrError = (
type: 'value' | 'error',
id: string,
text: string
) => {
setSignupInputs((prev) => ({
...prev,
[id]: {
...prev[id],
[type]: text,
},
}));
};
const handleCheckDuplicateIdOrNickname = (type: 'id' | 'nickname') => {
if (type === 'id') {
if (!/^[a-z]+[a-z0-9]{3,16}$/g.test(id.value)) {
setSignupInputsValueOrError(
'error',
'id',
'영문자로 시작하는 영문자 또는 숫자 4~15자'
);
return;
}
checkDuplicateIdRequest(id.value).then((data) => {
setDuplicateCheckedId(!data ? id.value : '');
setSignupInputsValueOrError('error', 'id', '');
alert(!data ? '사용 가능한 아이디입니다' : '중복된 아이디입니다');
});
} else {
if (nickname.value.length < 2) {
setSignupInputsValueOrError(
'error',
'nickname',
'닉네임은 2자 이상 입력해 주세요'
);
return;
}
checkDuplicateNicknameRequest(nickname.value).then((data) => {
setDuplicateCheckedNickname(!data ? nickname.value : '');
setSignupInputsValueOrError('error', 'nickname', '');
alert(!data ? '사용 가능한 닉네임입니다' : '중복된 닉네임입니다');
});
}
};
...
return (
<form onSubmit={handleSignUp}>
{signupInputsData.map(([id, type, title, placeholder]) => (
...
{(id === 'id' || id === 'nickname') && (
<button
onClick={() => handleCheckDuplicateIdOrNickname(id)}
>
중복확인
</button>
)}
<span className="text-sm tracking-tighter text-red-400">
{signupInputs[id].error}
</span>
...
);
}
또 중복이 아닐 때 duplicateCheckedNickname & Id state 중복되지 않은 현재 value를 담는데, 만약 중복 체크 후에 값을 변경할 수 있으니 가입하기를 눌러서 폼을 제출할 때 한 번 더 확인해야 한다. 그리고 나머지 input filed 값들도 유효성 검사ㅜ
만약 id input에 'test' 값이 있고 중복 체크를 하면 중복된 값이 아닐 시 duplicateCheckedId state에 'test'가 중복되면 ''이 담기는데 빈 문자열은 falsy 값이므로 !를 붙여서 true가 된다 그래서 true || 중복체크된 값이랑 input 값이 다른지
를 체크했다.
const handleSignUp = async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
if (!duplicateCheckedId || duplicateCheckedId !== id.value) {
alert('아이디 중복 확인을 해주세요');
return;
}
if (
!duplicateCheckedNickname ||
duplicateCheckedNickname !== nickname.value
) {
alert('닉네임 중복 확인을 해주세요');
return;
}
if (!/^(?=.*\d)(?=.*[a-zA-Z])[0-9a-zA-Z]{5,16}$/.test(pw.value)) {
setSignupInputsValueOrError('error', 'pw', '6~16자 영문, 숫자 조합');
return;
} else {
setSignupInputsValueOrError('error', 'pw', '');
}
if (pw.value !== pwCheck.value) {
alert('비밀번호가 일치하지 않습니다');
return;
}
signupRequest({
username: id.value,
nickname: nickname.value,
password: pw.value,
userImageUrl: profileImage.value || defaultProfileImage,
socialType: 'GENERAL',
})
.then((data) => {
setCurrentUser(data);
goToHome();
})
.catch((err) => {
console.log('signup error', err);
});
};
// 가입요청로직
이렇게 하면 필드가 공백인지도 걸러진당
가입 시 바로 로긴
별거 없는데 시간 엄청 날렸다.. 내가 javascript regExp랑 정규식을 몰랐고 정리가 안 된 채로 계속 수정하면서 개발해가지고 🤕 텀블벅 사이트처럼 input value state가 변경될 때마다 표시하고 싶엇는데 머가 계속 안 됐고 어쨌든 앞으로 조금 신경써야 하는 로직은 작게라도 계획을 세워놓고 개발해야겠다