본문 바로가기
포트폴리오

친환경 쇼핑몰 프로젝트 구축하기: 리액트와 리코일을 이용한 로그인 및 회원가입 페이지 구현 - 전역 상태 관리와 라우팅 적용 (3)

by 플라퉁 2023. 6. 26.
728x90
반응형

 

 

 

 

이번에는 프론트 리액트와 리코일을 이용하여 회원가입 및 로그인을 구현해보겠습니다.

 

먼저 App.tsx 입니다.

 

import React from "react";
import AppRoutes from "./app/AppRoutes";
import { RecoilRoot } from "recoil";


function App() {
 
  return (
    <div className="App">
      <RecoilRoot>
        <AppRoutes />
      </RecoilRoot>
    </div>
  );
}

export default App;

 

 

 

 

 

상태관리를 위해서 리코일을 사용합니다.

auth.ts입니다.

 

import { atom } from "recoil";
import axios from "axios";

interface User {
  username: string;
  email: string;
  token?: string;
}

export const userState = atom<User>({
  key: "user",
  default: { username: "", email: "" },
});

export const isLoggedInState = atom<boolean>({
  key: "isLoggedIn",
  default: localStorage.getItem("token") ? true : false,
});


export const login = async (formData: { email: string; password: string }) => {
  const response = await axios.post("http://api주소/auth/login", formData);
  const { username, email, token } = response.data;

  localStorage.setItem("token", token); // 로컬 스토리지에 토큰 저장

  return { username, email, token };
};



export const signup = async (formData: {
  username: string;
  email: string;
  password: string;
}) => {
  const response = await axios.post("http://api주소/auth/signup", formData);
  const { username, email, token } = response.data;

  localStorage.setItem("token", token); // 로컬 스토리지에 토큰 저장

  return { username, email, token };
};

export const logout = async () => {
    try {
      await axios.post("http://api주소/auth/logout");
  
      // 로컬 스토리지에서 토큰 제거
      localStorage.removeItem("token");
    } catch (error) {
      console.error("Error during logout:", error);
    }
};

 

 

 

 

 

 

리액트 라우트를 사용해 페이지 관리를 합니다. AppRoutes.tsx입니다.

 

import * as React from "react";
import { BrowserRouter, Route, Routes } from 'react-router-dom';
import Home from "../pages/Home/Home";
import SignUp from "../pages/SignUp/SignUp";
import Login from "../pages/LogIn/Login";
import Products from "../pages/Products/Products";
import Admin from "../pages/Products/Admin";


function AppRoutes() {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/login" element={<Login />} />
        <Route path="/signup" element={<SignUp />} />
        <Route path="/products" element={<Products />} />
        <Route path="/admin" element={<Admin />} />
        {/*  추가적인 라우트를 이곳에 작성해주세요  */}
      </Routes>
    </BrowserRouter>
  );
}

export default AppRoutes;

 

 

 

 

 

 

마지막으로 로그인 페이지입니다.

 

import * as React from "react";
import Header from "../Header/Header";
import { useState } from "react";
import { useNavigate } from 'react-router-dom';
import { useSetRecoilState } from "recoil";
import { userState, isLoggedInState, login } from "../../Recoil/Atoms/auth";
import '../../assets/scss/login.css';

const Login: React.FC = () => {
    const [formData, setFormData] = useState({ email: '', password: '' });
    const setUser = useSetRecoilState(userState);
    const setIsLoggedIn = useSetRecoilState(isLoggedInState);
    const navigate = useNavigate();

    const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
        const { name, value } = e.target;
        setFormData({ ...formData, [name]: value });
    };

    const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
        e.preventDefault();
        try {
          const loggedInUser = await login(formData);
          setUser(loggedInUser);
          setIsLoggedIn(true);
          navigate("/")
        } catch (error) {
          console.error(error); // 이 부분은 에러처리를 원하는 방식으로 변경하실 수 있습니다.
        }
    };

    const handleClick = (e: React.MouseEvent<HTMLAnchorElement>) => {
        e.preventDefault();
        navigate("/SignUp")
    };

  return (
    <div className="Login">
      <Header textColor={'#4caf50'}></Header>
      <div className="memberBox">
        <div className="loginBox">
            <h3>로그인을 해주세요</h3>
            <form onSubmit={handleSubmit}>
                <input 
                    type="email"
                    placeholder="Email"
                    value={formData.email}
                    name="email"
                    onChange={handleChange}
                >
                </input>
                <input
                    type="password"
                    placeholder="Password"
                    value={formData.password}
                    name="password"
                    onChange={handleChange}
                >
                </input>
                <button type="submit">login</button>
            </form>
        </div>
        <div className="signupBox">
            <h3>회원가입을 해주세요</h3>
            <a onClick={handleClick}>회원가입 페이지로</a>
        </div>
      </div>
    </div>
  );
};

export default Login;

 

리코일을 사용해서 전역적으로 useState를 관리하기 위해 이렇게 작성하였습니다.

 

추후에 세부적으로 validation이나 보안관련 추가적인 기능들을 구현할 예정입니다.

 

다음에는 제품을 등록하는 시간으로 돌아오겠습니다. 

 

 

 

감사합니다.

 

 

 

728x90
반응형

댓글