본문 바로가기
교육후 개인공부/React

[Next.js] 리덕스와 자체 로그인연결

by 뭉지야 2024. 4. 3.
728x90

1. 일단  store를 만들었다

 

redux/store.js

import { createSlice, configureStore, PayloadAction } from "@reduxjs/toolkit";

const initialState = {
  value: {
    email: "snrnsi",
    pw: "123",
  },
};

const LoginState = createSlice({
  name: "login",
  initialState,
  reducers: {
    //로그인한 유저 변경되는게 들어가야한다.
    setLogin: (state, action) => {
      state.user = action.payload;
    },
    setLogout: state => {
      state.email = null;
      state.pw = null;
    },
  },
});

export const { setLogin, setLogout } = LoginState.actions;

export default configureStore({
  reducer: {
    loginState: LoginState.reducer,
  },
});

 

저렇게하고 dev tools를 확장프로그램으로 설치해서 입력된 email과 pw가 들어가는지 확인했고 

어떤 데이터형태로 들어가는지도 확인했다.

데이터는 value와 다른 객체로 나란히 들어갔고, 입력된 email과 pw는 user라는 이름의 객체안에 들어갔다.

 

2. 일단은 dispatch와 useSelector를 하기전에 provider작업을 먼저 했다.

 

redux/provider.js

"use client";

import { Provider } from "react-redux";
import store from "./store";

export default function ReduxProvider({ children }) {
  return <Provider store={store}>{children}</Provider>;
}

 

3. layout에서도 작업을 해줘야한다.

import { Inter } from "next/font/google";
import "./globals.css";
import Link from "next/link";
import LogoutBtn from "./LogoutBtn";
import { getServerSession } from "next-auth";
import { authOptions } from "@/pages/api/auth/[...nextauth]";
import ReduxProvider from "../redux/provider";
//import TestBtn from "./TestBtn";
import HeaderLoginP from "./HeaderLoginP";

const inter = Inter({ subsets: ["latin"] });

export const metadata = {
  title: "Create Next App",
  description: "Generated by create next app",
};

export default async function RootLayout({ children }) {
  let session = await getServerSession(authOptions);
  // console.log(session);

  return (
    <html lang="en">
      <body className={inter.className}>
        <div className="navbar">
          <Link href="/" className="logo">
            Home
          </Link>
          <Link href="/list">List</Link>
          <Link href="/cart">Cart</Link>
          <Link href="/board">Q&A</Link>

          {session ? (
            <span className="head-design1">
              <div className="head-memberInfo">{session.user.name}</div>
              <LogoutBtn />
            </span>
          ) : (
            <div className="head-design1">
              <ReduxProvider>
                <HeaderLoginP />
              </ReduxProvider>
            </div>
          )}
        </div>

        <ReduxProvider>{children}</ReduxProvider>

        <div className="footer">Copyright 2024 by Moon</div>
      </body>
    </html>
  );
}

 

로그인되었을때 바뀌는 부분때문에 ReduxProvider가 이중으로 사용되어있다.

 

4. 이제 로그인버튼을 누르면 입력한 email과 pw를 가져오게 dispatch를 해야한다.

(입력한 액션값을 dispatch가 가져온다.)

 

/login/Part.js

"use client";
//자체 로그인부분

import axios from "axios";
import { useState } from "react";
import { useRouter } from "next/navigation";
import { useSelector, useDispatch } from "react-redux";
import { setLogin } from "../../redux/store";

export default function Part() {
  const [email, setEmail] = useState("");
  const [pw, setPw] = useState("");
  //const [info, setInfo] = useState("");
  const dispatch = useDispatch();

  const handleEmail = e => {
    setEmail(e.target.value);
  };
  const handlePw = e => {
    setPw(e.target.value);
  };
  let router = useRouter();

  const handleLogin = () => {
    //setEmail(email);
    //dispatch(setLogin({ email, pw })); //디스패치가 입력된 액션값을 가지고 온다.
    LoginAxios();
    // console.log(email, pw);
  };
  // const user2 = useSelector(state => state.loginState.user);
  // console.log(user2?.email);

  const LoginAxios = () => {
    const body = { email, pw };
    axios
      .post("/api/auth/login", body)
      //.then(res => console.log(res.data))
      .then(res => {
        setEmail(res.data.email),
          setPw(res.data.pw),
          alert("로그인성공"),
          dispatch(setLogin({ email, pw })); //디스패치가 입력된 액션값을 가지고 온다. 이걸 원하는 곳에 가서 selectorr로 쓰면된다
        router.push("/");
      })
      .catch(err => {
        alert("실패"), setEmail(""), setPw("");
      });
  };

  return (
    <div>
      <h4>Email</h4>
      <input value={email} onChange={handleEmail} />
      <h4>Password</h4>
      <input type="password" value={pw} onChange={handlePw} />
      <button onClick={handleLogin}>로그인</button>
    </div>
  );
}

 

5. 이렇게 가져온 값을 useSelector를 이용하여 헤더부분에서 보일수있게할거다.

HeaderLoginP.js

"use client";

import { useSelector } from "react-redux";
import LoginBtn from "./LoginBtn";
import SignupBtn from "./SignupBtn";
import LogoutBtn from "./LogoutBtn";

export default function HeaderLoginP() {
  const user2 = useSelector(state => state.loginState.user);
  // console.log(user2?.email);
  return (
    <div>
      {/* <h2>ㅌㅌ님</h2> */}
      {/* user2가 있으면 user2.email로 보이게 하고 , 없으면 안녕하세요만 보이게 삼항연산자하기 */}
      {user2 ? (
        <div>
          <h2>{user2.email}님</h2>
          <LogoutBtn />
        </div>
      ) : (
        <div>
          <LoginBtn />
          <SignupBtn />
        </div>
      )}
    </div>
  );
}

 

 

이렇게 하여 리덕스툴킷을 이용해서 자체로그인했을때나 Oauth를 이용해서 로그인을 했을때 둘다 헤더부분에 회원의 정보가 뜰수있게 설정했다.

 

리덕스툴킷을 next.js에서 적용한다니까 뭔가 복잡하기도 하고 

리덕스는 "use client"에서만 사용하여야한다는 부분때문에 복잡하기도 했는데

들어오는 데이터의 형태나 정보를 하나씩 확인하여 차근차근 생각하니 진행이 되었다.

 

좀 막막하여 이렇게 저렇게 찾아보아도 정보의 한계가 있는것 같고 에러도 계속 발생하여 골치아팠지만

일단 성공하여서 기분좋다!!

 

로그아웃부분은 아직 구현 완료가 아니지만 계속 업그레이드해야징

728x90

'교육후 개인공부 > React' 카테고리의 다른 글

[Next.js] 리덕스와 장바구니기능  (0) 2024.04.12
[React] Suspense  (0) 2024.04.03
[Next.js] Oauth와 자체 로그인 같이 구현  (0) 2024.03.23
[React] useCallback  (0) 2024.03.19
[React] useMemo  (0) 2024.03.19