원글 페이지 : 바로가기
로그인 페이지/ 로그인 시 전화면으로 이동/ 로그아웃시 로그인, 회원가입 화면 page > login
const [formError, setFormError] = useState
const [tabLogin, setTabLogin] = useState
const router = useRouter();
const { isLogin } = useAuth();
useEffect(() => {
// 로그인된 상태에서 /login 들어오면 홈으로
if (isLogin) {
void router.replace(“/”);
} else {
// active 클래스 1초 뒤 삭제
const timer = setTimeout(() => {
setFormError(false);
}, 1000);
return () => {
clearTimeout(timer);
};
}
}, [formError, isLogin]); (isLogin 하단 context API 코드 참고) – 로그인, 회원가입에서 setFormError가 넘어오면 클래스 active가 추가된다. 스타일을 위해서 1초뒤 삭제했다. – 로그인을 한 상태에서 로그인페이지에 다시 올 수 도 있으니 그때는 / 홈으로 이 로그인 컴포넌트 componentes > formLogin.tsx const emailInput = useRef
const pwdInput = useRef
const router = useRouter();
async function login(email: string, password: string) {
try {
const userLogin = await signInWithEmailAndPassword(auth, email, password);
setFormError(false);
router.back();
return userLogin;
} catch (error) {
console.log(error);
setFormError(true);
return null;
}
}
const onSubmit = async (e: React.FormEvent
e.preventDefault();
const email = emailInput.current?.value ?? “”;
const password = pwdInput.current?.value ?? “”;
await login(email, password);
}; – 로그인을 하면 이전 화면으로 이동 – onSubmit 여기서도 email, password는 ref로 input 값을 받아왔다. Warning: Can’t perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup – 원래 onSubmit에 router.back()을 했는데 오류가 나왔었다. 찾아보니 컴포넌트가 이미 언마운트되었는데도 상태를 업데이트하려고 하면 나온다고 한다. 그래서 페이지 이동을 login에서 진행되게 바꿔주었다. https://kyounghwan01.github.io/blog/React/cant-perform-a-React-state-update-on-an-unmounted-component/#%E1%84%87%E1%85%A1%E1%86%AF%E1%84%89%E1%85%A2%E1%86%BC-%E1%84%8B%E1%85%B5%E1%84%8B%E1%85%B2 로그아웃 export default function LayoutHeader({ className }: { className?: string }) {
const { isLogin } = useAuth();
const { currentModal, openModal, closeModal } = useModal();
// 로그아웃 클릭 이벤트
const onClickLogout = async () => {
try {
await signOut(auth);
openModal(“logout”);
} catch (error) {
console.log(error);
}
}; 헤더에 있는 로그아웃 버튼 – 버튼을 클릭하면 로그아웃이 되고 모달을 띄운다. 💡로그아웃 header.tsx 더보기 export default function LayoutHeader({ className }: { className?: string }) {
const isMobile = useIsMobile();
const [menuOpen, setMenuOpen] = useState
const { isLogin } = useAuth();
const { currentModal, openModal, closeModal } = useModal();
// 로그아웃 클릭 이벤트
const onClickLogout = async () => {
try {
await signOut(auth);
openModal(“logout”);
} catch (error) {
console.log(error);
}
};
// 모바일 메뉴 토글 클릭이벤트
const onClickMenu = () => {
setMenuOpen((prev) => !prev);
};
return (
<>
요즘캠핑
{!isMobile ? (
) : (
로그인
) : (
)}
)}
{/* 모바일메뉴 */}
{isMobile && (
)}
{/* 후기, 내 캠핑장 alert */}
{currentModal === “logout” && (
)}
>
);
} 💡전체코드 formLogin.tsx 더보기 export default function FormLogin({
formError,
setFormError,
}: {
formError: boolean;
setFormError: (value: boolean) => void;
}) {
const emailInput = useRef
const pwdInput = useRef
const router = useRouter();
async function login(email: string, password: string) {
try {
const userLogin = await signInWithEmailAndPassword(auth, email, password);
setFormError(false);
router.back();
return userLogin;
} catch (error) {
console.log(error);
setFormError(true);
return null;
}
}
const onSubmit = async (e: React.FormEvent
e.preventDefault();
const email = emailInput.current?.value ?? “”;
const password = pwdInput.current?.value ?? “”;
await login(email, password);
};
return (
Password
{formError &&
이메일, 비밀번호를 확인해주세요.
}
);
} 💡 전체 코드 useAuth – 나는 우선 유저정보는 필요없고 로그인 상태만 필요해서 login이 됐는지 안됐는지만 확인하는 용도로 context를 만들었다. 더보기 import { auth } from “@/firebase/firebase”;
import { onAuthStateChanged } from “firebase/auth”;
import { createContext, useContext, useEffect, useState } from “react”;
interface AuthContextType {
isLogin: boolean;
}
export const AuthContext = createContext
isLogin: false,
});
export const AuthProvider = ({ children }: { children: React.ReactNode }) => {
const [isLogin, setIsLogin] = useState
useEffect(() => {
onAuthStateChanged(auth, (user) => {
if (user) {
setIsLogin(true);
} else {
setIsLogin(false);
}
});
}, [auth]);
return (
);
};
export const useAuth = () => {
const context = useContext(AuthContext);
if (context === undefined) {
throw new Error(“context가 없을 경우”);
}
return context;
}; 💡 전체 코드 login 더보기 export default function index() {
const [formError, setFormError] = useState
const [tabLogin, setTabLogin] = useState
const router = useRouter();
const { isLogin } = useAuth();
useEffect(() => {
// 로그인된 상태에서 /login 들어오면 홈으로
if (isLogin) {
void router.replace(“/”);
} else {
// active 클래스 1초 뒤 삭제
const timer = setTimeout(() => {
setFormError(false);
}, 1000);
return () => {
clearTimeout(timer);
};
}
}, [formError, isLogin]);
if (isLogin) {
return null;
}
return (
Welcome
Daily Camping!
홈 화면으로 돌아가기
{/* 로그인/ 회원가입 탭 */}
{tabLogin ? (
Login
아래 테스트 이메일로 로그인 가능합니다:)
) : (
Sign Up
회원가입 입니다:)
)}
);
} 참고 블로그 https://velog.io/@jian09/Firebase-Auth-%EB%A1%9C%EA%B7%B8%EC%9D%B8-%EC%97%90%EB%9F%AC-%EC%B2%98%EB%A6%AC https://velog.io/@konveloper/Firebase-React-%EC%9D%B4%EB%A9%94%EC%9D%BC-%ED%9A%8C%EC%9B%90%EA%B0%80%EC%9E%85%EB%A1%9C%EA%B7%B8%EC%9D%B8-%EA%B5%AC%ED%98%84 https://velog.io/@minz-cha/React-Firebase%EB%A5%BC-%ED%86%B5%ED%95%B4-%ED%9A%8C%EC%9B%90%EA%B0%80%EC%9E%85-%EB%A1%9C%EA%B7%B8%EC%9D%B8-%EB%A1%9C%EA%B7%B8%EC%95%84%EC%9B%83-%EA%B8%B0%EB%8A%A5-%EA%B5%AC%ED%98%84