Skip to content

Commit

Permalink
Refactor (SignForm) : handleSubmit 함수에서 책임별 함수 분리
Browse files Browse the repository at this point in the history
  • Loading branch information
han-kimm committed Dec 10, 2023
1 parent 2018b77 commit 33c15ef
Show file tree
Hide file tree
Showing 11 changed files with 114 additions and 53 deletions.
1 change: 0 additions & 1 deletion components/Footer/Footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ interface Props {
}

export default memo(function Footer({ setRefForObserver }: Props) {
console.log("렌더링");
return (
<Container ref={setRefForObserver}>
<Copy>©codeit - 2023</Copy>
Expand Down
7 changes: 7 additions & 0 deletions components/Main/sign/Sign.type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,10 @@ export interface Signin {
export interface InputType {
type: "email" | "password" | "passwordCheck";
}

export type InputRef = {
current: null;
emBlur(): boolean;
pwBlur(): boolean;
pwChBlur(): boolean;
};
20 changes: 18 additions & 2 deletions components/Main/sign/SignEmLabel.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,29 @@
import { InputRef } from "@/components/Main/sign/Sign.type";
import { ErrorText, Input, StyledLabel } from "@/components/Main/sign/SignLabel.styled";
import useSignInput from "@/hooks/useSignInput";
import { RefObject, forwardRef, useImperativeHandle } from "react";

export default function SignEmLabel() {
export default forwardRef(function SignEmLabel(props, ref) {
const { error, input, p, handleBlur, handleFocus } = useSignInput();

useImperativeHandle(
ref,
() => {
return {
...(ref as RefObject<InputRef>).current,
emBlur() {
return handleBlur();
},
};
},
[]
);

return (
<StyledLabel $error={error}>
이메일
<Input type="email" name="email" placeholder="이메일을 입력해주세요" ref={input} onBlur={handleBlur} onFocus={handleFocus} $error={error} />
<ErrorText ref={p} />
</StyledLabel>
);
}
});
65 changes: 28 additions & 37 deletions components/Main/sign/SignForm.tsx
Original file line number Diff line number Diff line change
@@ -1,59 +1,50 @@
import { InputType, Signin } from "@/components/Main/sign/Sign.type";
import { StyledForm, SubmitButton } from "@/components/Main/sign/SignForm.styled";
import SignEmLabel from "@/components/Main/sign/SignEmLabel";
import { StyledForm, SubmitButton } from "@/components/Main/sign/SignForm.styled";
import SignPwLabel from "@/components/Main/sign/SignPwLabel";
import useInputAllBlur from "@/hooks/useInputAllBlur";
import { NextRouter, useRouter } from "next/router";
import { FormEvent } from "react";
import axios from "@/lib/axios";
import { validate_signin, validate_signup } from "@/utils/validate";
import { useRouter } from "next/router";
import { FormEvent, useState } from "react";

export default function SignForm() {
const [isError, SetIsError] = useState(false);
const { inputRef, allBlur } = useInputAllBlur();
const router = useRouter();
const signin = router.asPath === "/signin";

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

const inputs = Array.from(document.querySelectorAll("input"));
const ps = Array.from(document.querySelectorAll("label p"));
for (const i in inputs) {
const validateFunc = signin ? validate_signin : validate_signup;
const type = inputs[i].type as InputType["type"];
const value = inputs[i].value;

const res = await validateFunc({ type, value });
if (res) {
SetIsError(true);
ps[i].textContent = res;
continue;
}
SetIsError(false);
}
const isError = await allBlur();

if (!isError) {
try {
const postData = {
email: inputs[0].value,
password: inputs[1].value,
};
const url = signin ? "/api/sign-in" : "/api/sign-up";
const res = await axios.post(url, postData);
const token = res.data.data.accessToken;
sessionStorage.setItem("accessToken", token);
router.push(`/folder?a=${token}`, "/folder");
} catch {
ps.forEach((p) => (p.textContent = "계정 정보를 확인해주세요."));
}
postSignData(e.target, signin, router);
}
};

return (
<StyledForm onSubmit={handleSubmit}>
<SignEmLabel />
<SignPwLabel type="password" />
{signin ? null : <SignPwLabel type="passwordCheck" />}
<SignEmLabel ref={inputRef} />
<SignPwLabel ref={inputRef} type="password" />
{signin ? null : <SignPwLabel ref={inputRef} type="passwordCheck" />}
<SubmitButton>{signin ? "로그인" : "회원가입"}</SubmitButton>
</StyledForm>
);
}

const postSignData = async (obj: EventTarget, signin: boolean, router: NextRouter) => {
try {
const postData = new FormData(obj as HTMLFormElement);
const email = postData.get("email");
const password = postData.get("password");

const url = signin ? "/api/sign-in" : "/api/sign-up";
const res = await axios.post(url, { email, password });
const { accessToken, refreshToken } = res.data.data;
document.cookie = `accessToken=${accessToken}`;
document.cookie = `refreshToken=${refreshToken}`;

router.push(`/folder`);
} catch {
alert("아이디 또는 비밀번호가 일치하지 않습니다. 다시 입력해주세요.");
}
};
7 changes: 5 additions & 2 deletions components/Main/sign/SignLogo.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import { Signin } from "@/components/Main/sign/Sign.type";
import { Container, StyledImage, StyledLink, Text } from "@/components/Main/sign/SignLogo.styled";
import Link from "next/link";
import { useRouter } from "next/router";

export default function SignLogo() {
const router = useRouter();
const signin = router.asPath === "/signin";

export default function SignLogo({ signin }: Signin) {
return (
<Container>
<Link href="/">
Expand Down
27 changes: 25 additions & 2 deletions components/Main/sign/SignPwLabel.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { InputRef } from "@/components/Main/sign/Sign.type";
import { ErrorText, Input, OnOffButton, StyledLabel } from "@/components/Main/sign/SignLabel.styled";
import usePwVisibility from "@/hooks/usePwVisibility";
import useSignInput from "@/hooks/useSignInput";
import Image from "next/image";
import { RefObject, forwardRef, useImperativeHandle } from "react";

const TEXT = {
label: {
Expand All @@ -14,10 +16,31 @@ const TEXT = {
},
};

export default function SignPwLabel({ type }: { type: "password" | "passwordCheck" }) {
export default forwardRef(function SignPwLabel({ type }: { type: "password" | "passwordCheck" }, ref) {
const { error, input, p, handleBlur, handleFocus } = useSignInput();
const { toggleImg, handleToggle } = usePwVisibility(input);

useImperativeHandle(
ref,
() => {
if (type === "password") {
return {
...(ref as RefObject<InputRef>).current,
pwBlur() {
return handleBlur();
},
};
}
return {
...(ref as RefObject<InputRef>).current,
pwChBlur() {
return handleBlur();
},
};
},
[]
);

return (
<StyledLabel $error={error}>
{TEXT.label[type]}
Expand All @@ -37,4 +60,4 @@ export default function SignPwLabel({ type }: { type: "password" | "passwordChec
<ErrorText ref={p} />
</StyledLabel>
);
}
});
9 changes: 4 additions & 5 deletions components/Main/sign/SignSection.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
import { Signin } from "@/components/Main/sign/Sign.type";
import SignForm from "@/components/Main/sign/SignForm";
import SignLogo from "@/components/Main/sign/SignLogo";
import { StyledSection } from "@/components/Main/sign/SignSection.styled";
import SignSns from "@/components/Main/sign/SignSns";

export default function SignSection({ signin = false }: Signin) {
export default function SignSection() {
return (
<StyledSection>
<SignLogo signin={signin} />
<SignForm signin={signin} />
<SignSns signin={signin} />
<SignLogo />
<SignForm />
<SignSns />
</StyledSection>
);
}
7 changes: 5 additions & 2 deletions components/Main/sign/SignSns.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import { Signin } from "@/components/Main/sign/Sign.type";
import { Container } from "@/components/Main/sign/SignSns.styled";
import Image from "next/image";
import Link from "next/link";
import { useRouter } from "next/router";

export default function SignSns() {
const router = useRouter();
const signin = router.asPath === "/signin";

export default function SignSns({ signin }: Signin) {
return (
<Container>
<p>{signin ? "소셜 로그인" : "소셜 계정으로 가입하기"}</p>
Expand Down
19 changes: 19 additions & 0 deletions hooks/useInputAllBlur.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { InputRef } from "@/components/Main/sign/Sign.type";
import { useRef } from "react";

export default function useInputAllBlur() {
const inputRef = useRef<InputRef>(null);

const allBlur = () => {
if (!inputRef.current) return;
let res;
for (const f of Object.values(inputRef.current)) {
if (f instanceof Function) {
res = f();
}
}
return res;
};

return { inputRef, allBlur };
}
3 changes: 2 additions & 1 deletion hooks/useSignInput.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,10 @@ export default function useSignInput() {
if (res) {
setError(true);
p.current.textContent = res;
return;
return true;
}
setError(false);
return false;
};

const handleFocus = () => {
Expand Down
2 changes: 1 addition & 1 deletion pages/signin.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import SignSection from "@/components/Main/sign/SignSection";

export default function Signin() {
return <SignSection signin />;
return <SignSection />;
}

0 comments on commit 33c15ef

Please sign in to comment.