로그인, 회원가입 구현

김하은·2022년 12월 4일
0

로그인, 회원가입을 react-hook-form 사용해 바꿔보기

로그인

import { useMutation } from "@apollo/client";
import { yupResolver } from "@hookform/resolvers/yup";
import { Modal } from "antd";
import { useRouter } from "next/router";
import { useState } from "react";
import { useForm } from "react-hook-form";
import { useRecoilState } from "recoil";
import { accessTokenState } from "../../../../commons/libraries/store";
import {
  IMutation,
  IMutationLoginUserArgs,
} from "../../../../commons/types/generated/types";
import LogInPageUI from "./Login.presenter";
import { LOGIN_USER } from "./Login.queries";
import * as yup from "yup";
import { ILogInFormData } from "./Login.types";

export const schema = yup.object({
  email: yup
    .string()
    .email("이메일형식에 맞지 않습니다")
    .required("이메일을 입력해주세요"),
  password: yup
    .string()
    .matches(
      /^(?=.*[A-Za-z])(?=.*\d)(?=.*[@$!%*#?&])[A-Za-z\d@$!%*#?&]{8,}$/,
      "비밀번호는 영문, 숫자, 특수문자를 포함한 8자리 이내입니다"
    )
    .required("비밀번호를 입력해주세요"),
});

export default function LogIn() {
  const { register, handleSubmit, formState } = useForm<ILogInFormData>({
    resolver: yupResolver(schema),
    mode: "onChange",
  });

  const [accessToken, setAccessToken] = useRecoilState(accessTokenState);
  const router = useRouter();

  const [loginUser] = useMutation<
    Pick<IMutation, "loginUser">,
    IMutationLoginUserArgs
(LOGIN_USER);
  const onClickLogIn = async (data: ILogInFormData) => {
    try {
      const result = await loginUser({
        variables: {
          email:data.email
          password:data.password
        },
      });
      const accessToken = result.data?.loginUser.accessToken; // 얘를 글로벌스테이트에 담음 얘는
      if (!accessToken) {
        Modal.error({ content: "비밀번호를 확인해주세요" });
        return;
      }
      setAccessToken(accessToken);
      // 로컬스토리지에 저장
      localStorage.setItem("accessToken", accessToken); // 임시 사용. (나중에 지울예정)

      void router.push(`/`);
    } catch (error) {
      if (error instanceof Error) Modal.error({ content: error.message });
    }
  };
  return (
    <LogInPageUI
      // onChangeEmail={onChangeEmail}
      // onChangePassword={onChangePassword}
      register={register}
      handleSubmit={handleSubmit}
      formState={formState}
      onClickLogIn={onClickLogIn}
    />
  );
}

UI부분

import { ILogInPageUIProps } from "./Login.types";
import * as S from "./Login.styles";
import LogInInputsPage from "../../inputs/loginInput/Input";
import LoginUserButtonPage from "../../buttons/loginUserbutton/button";

export default function LogInPageUI(props: ILogInPageUIProps) {
 return (
   <S.LogInPage>
     <form>
       {" "}
       <S.LogIn>
         <S.LogInTitle>LOGIN PAGE</S.LogInTitle>
         이메일{" "}
         <LogInInputsPage type="text" register={props.register("email")} />
         <div>{props.formState.errors.email?.message}</div>
         비밀번호{" "}
         <LogInInputsPage
           type="password"
           register={props.register("password")}
         />
         <div>{props.formState.errors.password?.message}</div>
         <LoginUserButtonPage
           title={"로그인"}
           handleSubmit={props.handleSubmit}
           onClickLogIn={props.onClickLogIn}
</LoginUserButtonPage>
       </S.LogIn>{" "}
     </form>
   </S.LogInPage>
 );
}

LoginInput 컴포넌트 부분

import { ILogInInputsProps } from "./input.types";
import * as S from "./input.styles";

export default function LogInInputsPage(props: ILogInInputsProps) {
  return <S.LogInInput type={props.type} {...props.register} />;
}

LogInButton 컴포넌트 부분

import { IButtonPageProps } from "./button.types";
import * as S from "./button.styles";

export default function LoginUserButtonPage(props: IButtonPageProps) {
  return (
    <S.LogInButton
      type="button"
      onClick={props.handleSubmit(props.onClickLogIn)}

      {props.title}
    </S.LogInButton>
  );
}

회원가입

import { useMutation } from "@apollo/client";
import { yupResolver } from "@hookform/resolvers/yup";
import { Modal } from "antd";
import { useRouter } from "next/router";
import { useState } from "react";
import { useForm } from "react-hook-form";
import {
  IMutation,
  IMutationCreateUserArgs,
} from "../../../commons/types/generated/types";
import { withAuthYes } from "../hocs/withAuth";
import CreateUsersUI from "./CreateUsers.presenter";
import { CREATE_USER } from "./CreateUsers.queries";
import * as yup from "yup";
import { IFormDatas } from "../buttons/createUserbutton/button.types";

export const schema = yup.object({
  email: yup
    .string()
    .email("이메일형식에 맞지 않습니다")
    .required("필수 형식입니다"),
  name: yup.string().required("필수 형식입니다"),
  password: yup
    .string()
    .min(4, "최소 4자 이상을 입력해주세요")
    .matches(
      /^(?=.*[A-Za-z])(?=.*\d)(?=.*[@$!%*#?&])[A-Za-z\d@$!%*#?&]{8,}$/,
      "비밀번호는 영문, 숫자, 특수문자를 포함한 8자리 이내로 적어주세요"
    )
    .required("필수 형식입니다"),
});

function CreateUsers() {
  const { register, handleSubmit, formState } = useForm<IFormDatas>({
    resolver: yupResolver(schema),
    mode: "onChange",
  });

  const router = useRouter();
  const [createUser] = useMutation<
    Pick<IMutation, "createUser">,
    IMutationCreateUserArgs
(CREATE_USER);

  const onClickCreateUsers = async (data: IFormDatas) => {
    try {
      await createUser({
        variables: {
          createUserInput: {
            email: data.email
            name: data.name
            password: data.password,
          },
        },
      });
      Modal.success({ content: "회원가입이 완료되었습니다" });
      void router.push(`/login`);
    } catch (error) {
      if (error instanceof Error) Modal.error({ content: error.message });
    }
  };
  return (
    <CreateUsersUI
      register={register}
      handleSubmit={handleSubmit}
      formState={formState}
      onClickCreateUsers={onClickCreateUsers}
    />
  );
}
export default withAuthYes(CreateUsers);

회원가입 UI부분

import CreateUserButtonPage from "../buttons/createUserbutton/button";
import CreateUserInputsPage from "../inputs/createUsersInput/Input";
import { ICreateUsersUIProps } from "./CreateUsers.types";

export default function CreateUsersUI(props: ICreateUsersUIProps) {
  return (
    <>
      <form>
        이메일:{" "}
        <CreateUserInputsPage type="text" register={props.register("email")} />
        <div>{props.formState.errors.email?.message}</div>
        이름:{" "}
        <CreateUserInputsPage type="text" register={props.register("name")} />
        <div>{props.formState.errors.name?.message}</div>
        비밀번호:{" "}
        <CreateUserInputsPage
          type="password"
          register={props.register("password")}
        />
        <div>{props.formState.errors.password?.message}</div>
        <CreateUserButtonPage
          title={"회원가입하기"}
          handleSubmit={props.handleSubmit}
          onClickCreateUsers={props.onClickCreateUsers}
</CreateUserButtonPage>
      </form>{" "}
    </>
  );
}

createUserButton 컴포넌트 부분

import { IButtonPageProps } from "./button.types";

export default function CreateUserButtonPage(props: IButtonPageProps) {
  return (
    <button
      type="button"
      onClick={props.handleSubmit(props.onClickCreateUsers)}
   >
      {props.title}
    </button>
  );
}

회원가입 부분 input은 로그인input 과 동일하기에 따로 생성해주지 않았다.

0개의 댓글