[React] TODO LIST 만들기 (3) - Firebase (signInWithEmailAndPassword)로 로그인 하기

Kylie·2022년 11월 21일
0

[React] Todo List

목록 보기
3/6
post-thumbnail

1. 들어가기 전

저번 포스팅에서 이메일과 비밀번호를 사용하여 계정을 만들어보았습니다. 이번 시간에는 만든 이메일과 비밀번호를 사용하여 로그인을 해보겠습니다.


2. 목표

  • firebase signInWithEmailAndPassword 을 사용하여 로그인을 한다.
  • 로그인 정보를 가져와서 전역에서 사용할 수 있도록 한다.

3. 로그인

3.1 로그인 폼 만들기

src/pages/login.tsx

import React, { ChangeEvent, useState } from "react";
import { Link, useNavigate} from "react-router-dom";

// INTERFACE
import { UserInputInterface } from "../interfaces/user.interface";

// CSS
import { UserForm } from "../styles/userForm.styled";
import { Button, TextField } from "@mui/material";


export const Login = () => {
  const [inputs, setInputs] = useState<UserInputInterface>({
    email: "",
    password: "",
  });

  const { email, password } = inputs;

  const onChange = (e: ChangeEvent<HTMLInputElement>) => {
    const { name, value } = e.currentTarget;
    setInputs({ ...inputs, [name]: value });
  };

  return (
    <UserForm>
      <div className={"doc-title"}>
        <span>Login</span>
      </div>
      <article className={"user-form-article"}>
        <div className={"user-form-wrap"}>
          <div className={"user-form"}>
            <form onSubmit={onSubmit}>
              <TextField
                onChange={onChange}
                value={email}
                label="email"
                variant="outlined"
                name={"email"}
                type={"email"}
                required
              />
              <TextField
                onChange={onChange}
                value={password}
                label="password"
                variant="outlined"
                name={"password"}
                type={"password"}
                required
              />
              <Button
                variant={"contained"}
                type={"submit"}
                disabled={
                  email.length !== 0 && password.length !== 0 ? false : true
                }
              >
                Log In
              </Button>
            </form>
          </div>
          <div className={"cont-link"}>
            <Link
              to={"/signup"}
              style={{ textDecoration: "none", color: "inherit" }}
            >
              Not a member yet?
            </Link>
          </div>
        </div>
      </article>
    </UserForm>
  );
};

💡 onChange 함수까지는 회원가입 절차와 동일하기 때문에 그대로 사용하겠습니다. 회원가입 때와 마찬가지로 모든 input에 값이 있을 때 버튼이 활성화 됩니다.


3.2 onSubmit

이제 본격적으로 로그인 폼을 submit 해보겠습니다.
폼을 제출할 때 firebase의 signInWithEmailAndPassword 을 사용하여 유저 정보를 가져오겠습니다. 유저 정보를 성공적으로 가져왔다면 '/'
경로로 이동하도록 하겠습니다.


추가 부분만 작성하겠습니다.

// FIREBASE
import { firebaseAuth } from "../initFirebase";
import { signInWithEmailAndPassword } from "firebase/auth";

export const Login = () => {

// ...기존 내용 

  const onSubmit = async (e: ChangeEvent<HTMLFormElement>) => {
    e.preventDefault();
    await signInWithEmailAndPassword(firebaseAuth, email, password)
      .then((userCredential) => {
        const user = userCredential.user;
        console.log(user);
        navigate("/");
      })
      .catch((error) => {
        const errorCode = error.code;
        const errorMessage = error.message;
        console.warn(`${errorCode} = ${errorMessage}`);
      });
  };

   // .. return 부분
}


📌 Firebase 공식 문서 - 이메일 주소와 비밀번호로 사용자 로그인




이제 이메일 / 비밀번호를 사용하여 로그인을 할 수 있습니다. 로그인 한 회원의 정보를 앱 전반적으로 사용하면 더 편리하게 사용할 수 있을 것 같습니다. 지금부터 앱 전반적으로 유저 정보를 사용하는 방법에 대해 알아보겠습니다.


4. 로그인 한 유저 정보 받아오기

4.1 App.tsx 수정

앱이 실행할 때 Firebase의 onAuthStateChanged을 사용하여 현재 로그인한 유저의 uid 값을 가져옵니다. 그 다음 Firestore에 저장한 user 정보를 가져와서 userInfo 변수에 넣어두겠습니다. 앞으로 이 userInfo가 앱 전반적으로 사용하게 될 유저의 정보입니다.


src/App.tsx

import React, { useEffect, useState } from "react";

// FIREBASE
import { firebaseAuth, fireStoreJob } from "./initFirebase";
import { onAuthStateChanged } from "firebase/auth";
import { collection, query, where, getDocs } from "firebase/firestore";

// COMPONENTS
import { AppRouter } from "./routes/Router";

import "./styles/App.css";
import { UserInterface } from "./interfaces/user.interface";

const App = () => {
  const [init, setInit] = useState<boolean>(false);
  const [isLogin, setIsLogin] = useState<boolean>(false);
  const [userInfo, setUserInfo] = useState<UserInterface | null>(null);
  useEffect(() => {
    onAuthStateChanged(firebaseAuth, async (user) => {
      if (user) {
        // 'users' collection에서 유저 정보 가져오기
        const q = query(
          collection(fireStoreJob, "users"),
          where("uid", "==", user.uid)
        );
        const querySnapshot = await getDocs(q);
        querySnapshot.forEach((doc) => {
          const data = doc.data();
          // 유저 정보 저장
          setUserInfo({
            uid: data.uid,
            email: data.email,
            displayName: data.displayName,
            date_created: data.date_created,
          });
        });
        setIsLogin(true);
      } else {
        setIsLogin(false);
      }
      setInit(true);
    });
  }, []);

  return (
    <>
      {" "}
      {init ? (
        <AppRouter isLogin={isLogin} userInfo={userInfo} />
      ) : (
        "Initializing..."
      )}
    </>
  );
};

export default App;

앱이 실행될 때 로그인한 유저가 있는 지 확인한 후 AppRouterisLogin 값과 userInfo를 전달하겠습니다.


📌 Firebase 공식 문서 - 현재 로그인한 사용자 가져오기


5. 라우터 수정

src/routes/Router.tsx

로그인 여부에 따라 다음과 같이 설정하겠습니다.

로그인 한 경우 : 메인 페이지로 이동 (유저 정보 전달)
로그인 하지 않은 경우 : 로그인 페이지로 이동


import React from "react";
import {BrowserRouter, Routes, Route} from "react-router-dom";

// INTERFACE
import {UserInterface} from "../interfaces/user.interface";

// COMPONENTS
import {SignUp} from "../pages/signUp";
import {Login} from "../pages/login";
import {Main} from "../pages/main";

type AppRouterType = {
    isLogin: boolean;
    userInfo: UserInterface | null;
};

export const AppRouter = ({isLogin, userInfo}: AppRouterType) => {
    return (
        <BrowserRouter>
            <Routes>
                {isLogin ? (
                    <>
                        <Route path="/" element={<Main userInfo={userInfo}/>}></Route>
                    </>
                ) : (
                    <>
                        <Route path="/" element={<Login/>}></Route>
                        <Route path="/signup" element={<SignUp/>}></Route>

                    </>
                )}
            </Routes>
        </BrowserRouter>
    );
};

로그인 여부에 따라 각 pages에 다른 값을 전달하도록 했습니다. 이제 로그인 한 유저의 정보를 main에서도 받을 수 있습니다. main에서 어떻게 사용할 지는 다음 포스팅에서 자세히 작성하도록 하겠습니다.

profile
올해보단 낫겠지....

0개의 댓글