LogIn μν, μ μμμ κ΄λ¦¬νκΈ°(feat. Redux Toolkit) π
src/pages/LogInPage.js π΅
import React, { useState, useEffect } from "react";
import styled from "@emotion/styled";
import { loginUser } from "../modules/authSlice";
import { useNavigate } from "react-router-dom";
import ComponentWrapper from "../components/common/ComponentWrapper";
import { useDispatch } from "react-redux";
import { useSelector } from "react-redux";
const LogInTitle = styled.p`
text-align: center;
margin: 0px;
font-weight: bolder;
font-size: 40px;
`;
const LogInFormWrapper = styled.div`
/* display: flex;
flex-direction: column;
justify-content: center; */
/* min-width: 375px;
width: 100%;
height: 500px; */
/* margin: 0 auto; */
`;
const FormLabel = styled.p`
font-size: 16px;
margin-bottom: 8px;
`;
const FormInput = styled.input`
padding: 20px;
margin-bottom: 16px;
border: 1px solid #ccc;
border-radius: 8px;
font-size: 16px;
width: 100%;
max-width: 600px;
`;
const SubmitButton = styled.button`
background-color: black;
color: #fff;
padding: 20px;
border: none;
border-radius: 8px;
font-size: 18px;
font-weight: bolder;
cursor: pointer;
width: 100%;
&:hover {
background-color: #fff;
color: black;
border: 2px solid black;
}
`;
const LogInPage = () => {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const navigate = useNavigate();
const dispatch = useDispatch();
const isAuthenticated = useSelector((state) => state.auth.isAuthenticated);
const goToSignUp = () => {
navigate("/signup");
};
const handleSignIn = (e) => {
e.preventDefault();
dispatch(loginUser({ email, password }));
};
useEffect(() => {
if (isAuthenticated) {
navigate("/");
}
}, [isAuthenticated]);
return (
<ComponentWrapper
style={{
display: "flex",
justifyContent: "center",
alignItems: "center",
}}
>
{/* λͺ¨λ°μΌ 900px μ΄ν */}
<form onSubmit={handleSignIn}>
<LogInTitle>λ‘κ·ΈμΈ</LogInTitle>
<LogInFormWrapper>
<h2>μ΄λ©μΌ λ‘κ·ΈμΈ</h2>
<FormLabel>Email</FormLabel>
<FormInput
type="email"
placeholder="μμ΄λ(μ΄λ©μΌ μ£Όμ)λ₯Ό μ
λ ₯νμΈμ"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
<FormLabel>Password</FormLabel>
<FormInput
type="password"
placeholder="λΉλ°λ²νΈλ₯Ό μ
λ ₯νμΈμ"
value={password}
onChange={(e) => setPassword(e.target.value)}
/>
<SubmitButton>λ‘κ·ΈμΈ</SubmitButton>
<div style={{ display: "flex", columnGap: "8px" }}>
<p style={{ fontWeight: "bolder" }}> μ μ‘κ°μ΄ μ²μμ΄μ κ°μ?</p>
<p
style={{
color: "red",
fontWeight: "bolder",
cursor: "pointer",
}}
onClick={goToSignUp}
>
νμκ°μ
νκΈ°
</p>
</div>
</LogInFormWrapper>
</form>
</ComponentWrapper>
);
};
export default LogInPage;
src/modules/authSlice.js π΅
// authSlice.js
import { createSlice, createAsyncThunk } from "@reduxjs/toolkit";
import { auth } from "../firebase";
import { signInWithEmailAndPassword } from "firebase/auth";
// Firebase μΈμ¦μ μ¬μ©νμ¬ μ¬μ©μ λ‘κ·ΈμΈ μ²λ¦¬
export const loginUser = createAsyncThunk(
"auth/loginUser",
async (credentials) => {
const { email, password } = credentials;
console.log(credentials);
try {
const userCredential = await signInWithEmailAndPassword(
auth,
email,
password
);
console.log(userCredential);
return userCredential.user.email;
} catch (error) {
console.log(error);
throw error;
}
}
);
const authSlice = createSlice({
name: "auth",
initialState: {
user: null,
isAuthenticated: false,
},
extraReducers: (builder) => {
builder.addCase(loginUser.fulfilled, (state, action) => {
console.log(action.payload);
state.user = action.payload;
console.log(state.user);
state.isAuthenticated = true;
});
},
});
export default authSlice.reducer;
ν΄κ²° κ³Όμ π’
μ΄λ€ actionμ νν¨μ μμ΄, νΉν κ°λ°μλ κ·Έλ₯...
λ°μμ λλ΅μ ν΄μλ μ λλ€. μ μ μν κ΄λ¦¬
μ λν κ·Όκ±°λΆν° μμ νκ³ μ νλ€.
μ μ μν κ΄λ¦¬λ, μννΈμ¨μ΄ μ ν리μΌμ΄μ
λ΄μμ μ¬λ¬ μ»΄ν¬λνΈλ λͺ¨λ κ°μ 곡μ λλ λ°μ΄ν°μ μνλ₯Ό ν¨μ¨μ μΌλ‘ κ΄λ¦¬νλ λ°©λ²λ‘ μ€ νλμ΄λ€. 볡μ‘ν λ°μ΄ν°λ₯Ό νλμ νμΌμμ κ΄λ¦¬ν¨μΌλ‘μ¨ μ½λμ μμΈ‘ κ°λ₯μ±κ³Ό λλ²κΉ
μ ν¨μ¨μ±, μ¦ μμ°μ±μ μ κ³
νλ λ°μ κ·Έ λ³Έμ§μ΄ μλ€.
μ μ½λλ λ‘κ·ΈμΈμ form νκ·Έμ μ°λλμ΄ μλ ν¨μμ΄λ€. ν΅μ¬μ dispatchμ΄λ€. form νκ·Έ λ΄λΆμμ μ 곡νλ emailκ³Ό passwordλ₯Ό reducerλ‘ μ λ¬νλ μ λμ, μ΅μνμ μν λ§μ μννκ³ μλ€. μ μ μνμ λ³Έμ§μ λ§κ² λ°μ΄ν°μ μνμ λν κ°κ³΅μ ν΄λΉ ν¨μμμ μ΄λ£¨μ΄μ§μ§ μμ κ²μ΄λ€.
μ¬μ©μ λ‘κ·ΈμΈμ μ²λ¦¬νλ λΉλκΈ° ν¨μλ€. dispatchλ₯Ό ν΅ν΄ μ λ¬ν emailκ³Ό passwordλ μ ν¨μκ° λ°μ κ²μ΄λ€.
μ²μμλ ꡬκΈλ§μ ν΅ν΄ auth.signInWith~~
λ°©μμΌλ‘ μ½λλ₯Ό μμ±νλλ°, μ μλ¬κ° consoleμ μ°νλ€. firebase V9μμ ν¨μ μ¬μ© λ°©μμ΄ λ¬λΌμ‘κΈ°μ λ°μν μλ¬μλ€. μ μ½λμ²λΌ authλ₯Ό sign ν¨μ λ΄λΆμ λ£μ΄μ£Όλ λ°©μμΌλ‘ ν΄κ²°νλ€.
λ€μ μλ¬λ try λ¬Έ λ΄λΆμ return λΆλΆμμ λ°μνλ€. μ§λ ¬νμ κ΄ν λ΄μ©μ λ€λ£¨κ³ μλ€. μ§λ ¬ν μ체μ λν΄ λ€λ£¨λ©΄ μ½λ©μ μ¬κΈ°μ λ©μΆ κ² κ°λ€κ³ νλ¨νλ€. κ°λ¨ν μ 리νλ©΄, reduxμ actionμλ λΉμ§λ ¬νλ κ°μ΄ ν¬ν¨λμ΄ μμΌλ©΄ ν΄λΉ μλ¬κ° λ°μνλ€. firebaseμ μ¬μ©μ κ°μ²΄λ 볡μ‘ν λ΄λΆ ꡬ쑰λ₯Ό κ°μ§κ³ μκΈ°μ μ§λ ¬ννκΈ° μ΄λ ΅λ€κ³ νλ€. λ°λΌμ νμ¬λ‘μλ μ¬μ©μ κ°μ²΄λ₯Ό ν΅μΌλ‘ returnνλ κ²μ΄ μλλΌ νμν μ λ³΄λ§ μΆμΆνλ λ°©μμ ννκ³ , μλ¬λ μ¬λΌμ‘λ€.
κ²°λ‘ μ μΌλ‘ fulfilled λμμ λ μ΄κΈ°κ° userλ μ¬μ©μμ emailλ‘ μ λ°μ΄νΈ λλ€.
λ€μμ μ€λ λ§μ£Όν λ§μ§λ§ μλ¬λ€.
νμ΄μ§ μ΄λμ λν λ‘μ§μ useEffect ν¨μ μΈλΆμμ μμ±ν νμ λ°μν μλ¬μλ€.
isAuthenticationμ ν΅ν΄ useEffect λ΄λΆμμ νμ΄μ§ μ΄λμ μ²λ¦¬νλ€. μ¦, λ‘κ·ΈμΈμ μ±κ³΅νλ©΄ homeμΌλ‘ μ΄λνλ€. κ·Έλ°λ° μ΄λμ΄ μ λλ€.
μμ‘΄μ± λ°°μ΄μ νΉμ valueλ₯Ό μ λ ₯ν΄μΌ νλ€. valueκ° λ³κ²½λ λλ§λ€ νΈμΆλλ©°, μ΄λ valueλ λ λλ§κ³Ό κ΄λ ¨λ κ°μ΄μ΄μΌ νλ€.
ν... λνλ―Όκ΅ λ§μΈ