npm install react-router-dom
모듈 설치
import { useState } from "react"; import LoginForm from "../../components/form/LoginForm"; import "../../styles/pages/account/signin.scss"; import { Link, useNavigate } from "react-router-dom"; import axios from "axios"; export default function Signip() { const [role, setRole] = useState<string>("student"); function showLoginForm(role: string) { setRole(role); } const navigate = useNavigate(); // axios const login = async (role: string, id: string, pw: string): Promise<void> => { try { const url = `${process.env.REACT_APP_API_SERVER}/api/login${ role === "student" ? "Student" : "Tutor" }`; await axios({ method: "post", url: url, data: { id: id, password: pw, }, }).then((res) => { if (!res.data.isLogin) { alert("로그인 실패 \n" + res.data); } else { navigate("/api"); } }); } catch (error) { console.error("로그인 오류", error); } }; return ( <> <div className="login_container"> <h2>{role === "student" ? "학생 " : "강사 "} 로그인</h2> <div className="go_to_sign_up"> <p>아직 회원이 아니신가요?</p> <Link to="/api/student">학생 회원가입</Link> <Link to="/api/tutor">강사 회원가입</Link> </div> <div className="role_toggle_btn"> <div className="student_btn"> <button onClick={() => showLoginForm("student")}>학생으로 로그인</button> </div> <div className="tutor_btn"> <button onClick={() => showLoginForm("tutor")}>강사로 로그인</button> </div> </div> <div className="login_box"> {role && <LoginForm role={role} login={login} />} <div className="find_id_pw"> <Link to="#">아이디 찾기</Link> | <Link to="#">비밀번호 찾기</Link> </div> </div> </div> </> ); }
import kakaoLogo from "../../assets/Kakao.png"; import { useForm } from "react-hook-form"; import PasswordInput from "../input/PasswordInput"; import { SigninData } from "../../types/interface"; interface Props { role: string; login: (role: string, id: string, pw: string) => Promise<void>; } interface SigninData { id: string; pw: string; } export default function LoginForm({ role, login }: Props) { const { register, handleSubmit, formState: { errors }, } = useForm<SigninData>({ mode: "onSubmit", defaultValues: { id: "", pw: "", }, }); const onSubmit = async (data: SigninData) => { try { const { id, pw } = data; await login(role, id, pw); } catch (error) { console.error("로그인 오류", error); } }; return ( <> <div className="login_wrapper"> <div className="basic_login"> <form name="login_form" onSubmit={handleSubmit(onSubmit)}> <label htmlFor="id">ID</label> <input type="text" {...register("id", { required: true })} id="id" autoComplete="username" /> <label htmlFor="pw">비밀번호</label> <PasswordInput type="password" {...register("pw", { required: true })} id="pw" /> <button type="submit">로그인</button> </form> {role === "student" && ( <div className="social_login"> <button type="button"> <img src={kakaoLogo} alt="카카오 로그인 버튼" width={25} /> 카카오톡 로그인 </button> </div> )} </div> </div> </> ); }
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faEye, faEyeSlash } from "@fortawesome/free-regular-svg-icons"; import React, { forwardRef, useState } from "react"; import "../../styles/components/input/password.scss"; interface PasswordProps extends React.HTMLProps<HTMLInputElement> { type: string; } // PasswordInput 컴포넌트에 ref를 전달하려고 시도했으나, 함수 컴포넌트는 ref를 직접 받을 수 없기 때문에 문제 발생! // 이 문제를 해결하기 위해 React.forwardRef를 사용 const PasswordInput = forwardRef<HTMLInputElement, PasswordProps>(({ type, ...rest }, ref) => { const [isShow, setIsShow] = useState(false); const handleClick = () => { setIsShow(!isShow); }; return ( <> <div className="pw_input_wrapper"> <input ref={ref} type={isShow ? "text" : type} autoComplete="current-password" {...rest} /> <div className="eye_icon" onClick={handleClick}> <FontAwesomeIcon icon={isShow ? faEyeSlash : faEye} /> </div> </div> </> ); }); export default PasswordInput;
드릅게 어려워 죽겄네...