Skip to content

Commit

Permalink
#202 refactor: useError 커스텀 훅으로 error 관리
Browse files Browse the repository at this point in the history
  • Loading branch information
wuzoo committed Aug 5, 2024
1 parent 8828ee5 commit b545520
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 60 deletions.
75 changes: 38 additions & 37 deletions src/page/signUp/info/hook/common/useInfoForm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,21 @@ import { getFormatDateString, getFormatNumberString, isValidDate } from '@/page/
import { ChangeEvent, FormEvent, useCallback, useEffect, useState } from 'react';
import { useNavigate } from 'react-router-dom';

import { useOverlay } from '@/common/hook';
import { useError, useOverlay } from '@/common/hook';

import { UserInfo } from '@/shared/api/signup/info/type';
import { DATE_MAXLENGTH, FORMATTED_DATE_MAXLENGTH, SUPPORTING_TEXT } from '@/shared/constant/form';
import { PATH } from '@/shared/constant/path';
import { useVerifyCodeMutation } from '@/shared/hook/api/useVerifyCodeMutation';
import { useToastAction } from '@/shared/store/toast';
import { hasKeyInObject } from '@/shared/util/typeGuard';

export type InfoFormData = Omit<UserInfo, 'password' | 'passwordChecker'>;

type InfoFormUserInput = InfoFormData & {
authCode: string;
};

type InfoError = Partial<InfoFormUserInput>;

const IS_EMPTY_STRING = {
name: SUPPORTING_TEXT.NAME,
birth: SUPPORTING_TEXT.BIRTH,
Expand All @@ -29,42 +28,51 @@ const IS_EMPTY_STRING = {

export const useInfoForm = () => {
const [info, setInfo] = useState<InfoFormUserInput>({ name: '', birth: '', univ: '', email: '', authCode: '' });
const [error, setError] = useState<InfoError>({ name: '', birth: '', univ: '', email: '', authCode: '' });

const { error, updateFieldError, clearFieldError } = useError({
name: '',
birth: '',
univ: '',
email: '',
authCode: '',
});

const { isOpen: isSelectOpen, open: onSelectOpen, close: onSelectClose, toggle: onSelectToggle } = useOverlay();

const { mutate: validateAuthCode, isSuccess: isAuthCodeValidated } = useVerifyCodeMutation(info.email, info.authCode);
const { mutate: verityCodeMutate, isSuccess: isVerified } = useVerifyCodeMutation(info.email, info.authCode);

const { createToast } = useToastAction();

const navigate = useNavigate();

useEffect(() => {
setError((prev) => ({ ...prev, univ: undefined }));
clearFieldError('univ');

onSelectClose();
}, [info.univ, onSelectClose]);
}, [onSelectClose, clearFieldError]);

const handleInfoChange = useCallback((e: ChangeEvent<HTMLInputElement>) => {
const { value, name: key } = e.target;
const handleInfoChange = useCallback(
(e: ChangeEvent<HTMLInputElement>) => {
const { value, name: key } = e.target;

setInfo((prev) => ({
...prev,
[key]: value,
}));
if (value !== '') {
setError((prev) => ({
setInfo((prev) => ({
...prev,
[key]: undefined,
[key]: value,
}));
}
}, []);
if (value !== '' && hasKeyInObject(error, key)) {
clearFieldError(key);
}
},
[clearFieldError, error]
);

const handleBirthChange = useCallback(
(e: ChangeEvent<HTMLInputElement>) => {
let { value } = e.target;

if (info.birth !== '') setError((prev) => ({ ...prev, birth: '' }));
if (info.birth !== '') {
clearFieldError('birth');
}

if (value.length === DATE_MAXLENGTH && info.birth.length === FORMATTED_DATE_MAXLENGTH) {
value = info.birth.replace(/-/g, '');
Expand All @@ -77,7 +85,7 @@ export const useInfoForm = () => {
birth: value,
}));
},
[info.birth]
[info.birth, clearFieldError]
);

const handleUnivSelect = useCallback((item: string) => {
Expand All @@ -89,12 +97,12 @@ export const useInfoForm = () => {

const validateDate = useCallback(() => {
if (info.birth === '' || !isValidDate(info.birth)) {
setError((prev) => ({ ...prev, birth: 'error' }));
updateFieldError('birth', 'error');
return false;
}

return true;
}, [info.birth]);
}, [info.birth, updateFieldError]);

const validateForm = useCallback(() => {
let isFormError = false;
Expand All @@ -109,20 +117,13 @@ export const useInfoForm = () => {
}
/** 선택된 대학교 검사 */
if (key === 'univ' && value === '') {
setError((prev) => ({
...prev,
univ: 'error',
}));
updateFieldError('univ', 'error');
isFormError = true;
return true;
}
/** 나머지 info 유효성 검사 */
if (value === '') {
setError((prev) => ({
...prev,
[key]: IS_EMPTY_STRING[key as keyof InfoFormUserInput],
}));

if (value === '' && hasKeyInObject(error, key)) {
updateFieldError(key, IS_EMPTY_STRING[key]);
if (key === 'authCode') {
createToast(SUPPORTING_TEXT.EMAIL_NOAUTH, 'error');
}
Expand All @@ -132,13 +133,13 @@ export const useInfoForm = () => {
});

return !isFormError;
}, [createToast, info, validateDate]);
}, [createToast, info, validateDate, updateFieldError, error]);

const handleSubmit = useCallback(
(e: FormEvent<HTMLFormElement>) => {
e.preventDefault();

if (!validateForm() || !isAuthCodeValidated) return;
if (!validateForm() || !isVerified) return;

const formData: InfoFormData = {
name: info.name,
Expand All @@ -153,7 +154,7 @@ export const useInfoForm = () => {
},
});
},
[info, isAuthCodeValidated, navigate, validateForm]
[info, isVerified, navigate, validateForm]
);

return {
Expand All @@ -162,8 +163,8 @@ export const useInfoForm = () => {
handleBirthChange,
handleUnivSelect,
handleSubmit,
validateAuthCode,
isAuthCodeValidated,
verityCodeMutate,
isVerified,
isSelectOpen,
onSelectOpen,
onSelectClose,
Expand Down
36 changes: 13 additions & 23 deletions src/page/signUp/info/hook/common/usePasswordForm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,18 @@ import { InfoFormData } from '@/page/signUp/info/hook/common/useInfoForm';

import { ChangeEvent, FormEvent, useCallback, useState } from 'react';

import { useError } from '@/common/hook';

import { UserInfo } from '@/shared/api/signup/info/type';
import { PASSWORD_VALID_FORMAT, SUPPORTING_TEXT } from '@/shared/constant/form';
import { hasKeyInObject } from '@/shared/util/typeGuard';

type PasswordFormData = Omit<UserInfo, keyof InfoFormData>;

type PasswordError = Partial<PasswordFormData>;

export const usePasswordForm = (prevData: InfoFormData) => {
const [info, setInfo] = useState<PasswordFormData>({ password: '', passwordChecker: '' });
const [error, setError] = useState<PasswordError>({ password: '', passwordChecker: '' });

const { error, setErrors, updateFieldError, clearFieldError } = useError({ password: '', passwordChecker: '' });

const { mutate: signUpMutate } = useSignupMutation();

Expand All @@ -24,35 +26,28 @@ export const usePasswordForm = (prevData: InfoFormData) => {
...prev,
[key]: value,
}));
if (value !== '') {
setError((prev) => ({
...prev,
[key]: undefined,
}));
if (value !== '' && hasKeyInObject(error, key)) {
clearFieldError(key);
}
},
[]
[error, clearFieldError]
);

const validateForm = useCallback(() => {
if (info.password === '') {
setError({
password: SUPPORTING_TEXT.PASSWORD,
});
updateFieldError('password', SUPPORTING_TEXT.PASSWORD);

return false;
}

if (info.passwordChecker === '') {
setError({
passwordChecker: SUPPORTING_TEXT.PASSWORD_CHECKER,
});
updateFieldError('passwordChecker', SUPPORTING_TEXT.PASSWORD_CHECKER);

return false;
}

if (info.password !== info.passwordChecker) {
setError({
setErrors({
password: SUPPORTING_TEXT.PASSWORD_NO_EQUAL,
passwordChecker: SUPPORTING_TEXT.PASSWORD_NO_EQUAL,
});
Expand All @@ -61,16 +56,13 @@ export const usePasswordForm = (prevData: InfoFormData) => {
}

if (!PASSWORD_VALID_FORMAT.test(info.password)) {
setError((prev) => ({
...prev,
password: SUPPORTING_TEXT.PASSWORD_INVALID,
}));
updateFieldError('password', SUPPORTING_TEXT.PASSWORD_INVALID);

return false;
}

return true;
}, [info]);
}, [info, updateFieldError, setErrors]);

const handleSubmit = useCallback(
(e: FormEvent<HTMLFormElement>) => {
Expand All @@ -85,8 +77,6 @@ export const usePasswordForm = (prevData: InfoFormData) => {
};

signUpMutate(formData);

console.log(formData);
},
[validateForm, info, signUpMutate, prevData]
);
Expand Down

0 comments on commit b545520

Please sign in to comment.