[개인 포트폴리오] [클라이밍 커뮤니티 SNS] 2. 코드 분석 <layout.js>
2024. 12. 20. 10:11ㆍ웹개발 포트폴리오
728x90
반응형
import { Outlet, Link, useNavigate } from "react-router-dom";
import styled from "styled-components";
import { auth } from "../firebase";
import { useState, useEffect } from "react";
import { onAuthStateChanged } from "firebase/auth";
import { signOut } from "firebase/auth";
const Wrapper = styled.div`
@media (max-width: 600px) {
grid-template-rows: auto 1fr auto; /* 헤더, 메인, 푸터 */
grid-template-columns: 1fr; /* 단일 열 구조 */
}
display: grid;
height: 100vh;
width: 100vw;
overflow-y: hidden;
position: relative; /* 콘텐츠가 배경 위에 위치하도록 설정 */
z-index: 1;
`;
const Background = styled.div`
position: fixed;
top: 0;
left: 0;
width: 20vw;
height: 100vh;
background-image: url('/sidebar.jpg');
background-size: cover;
background-position: center;
z-index: -1;
&::before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5); /* 50% 어두운 효과 */
z-index: 1;
}
`;
const Logo = styled.img`
width: 15vw;
margin-bottom: 2vh;
@media (max-width: 600px) {
display: none;
}
`;
const Sidebar = styled.div`
display: flex;
flex-direction: column;
padding: 20px;
width: 15vw;
height: 100vh;
position: fixed;
background-color: #403B36;
color: white;
@media (max-width: 600px) {
width: 10vw;
font-size: 0.64rem;
}
`;
const NavLink = styled(Link)`
margin-bottom: 1.5rem;
display: flex;
align-items: center;
text-decoration: none;
color: white;
img {
width: 2rem;
margin-right: 1rem;
@media (max-width: 600px) {
align-items: center;
width: 2rem;
margin: 0 auto;
&:hover {
img {
border-color: white;
}
}
}
}
span {
@media (max-width: 600px) {
display: none; /* 모바일 버전에서는 숨기기 */
}
}
`;
export default function Layout() {
const navigate = useNavigate();
const [userId, setUserId] = useState(null);
useEffect(() => {
const unsubscribe = onAuthStateChanged(auth, async (user) => {
if (user) {
setUserId(user.uid);
// 로그인된 상태에서 로그인 또는 회원가입 페이지 접근 시 로그아웃 처리
if (window.location.pathname === "/login" || window.location.pathname === "/create-account") {
try {
await signOut(auth); // 로그아웃
alert("로그아웃 되었습니다.");
navigate("/login"); // 로그인 페이지로 리다이렉트
} catch (error) {
console.error("로그아웃 중 오류 발생:", error);
}
}
} else {
setUserId(null);
}
});
return () => unsubscribe();
}, [navigate]);
const handleLogout = async (e) => {
e.preventDefault(); // NavLink의 기본 동작 중단
const confirmLogout = window.confirm("정말 로그아웃 하시겠습니까?");
if (!confirmLogout) return; // 취소를 누르면 함수 종료
try {
await signOut(auth);
alert("로그아웃 되었습니다.");
navigate("/login"); // 로그아웃 후 로그인 페이지로 이동
} catch (error) {
console.error("로그아웃 중 오류 발생:", error);
}
};
return (
<Wrapper>
<Sidebar>
<Background />
<Logo src="/logo.png" alt="Logo" />
<NavLink to="/">
<img src="/home.png" alt="Home Icon" />
<span>홈</span>
</NavLink>
<NavLink to="/posting">
<img src="/posting.png" alt="Post Icon" />
<span>포스팅</span>
</NavLink>
{userId && (
<NavLink to={`/profile/${userId}`}>
<img src="/profile.png" alt="Profile Icon" />
<span>프로필</span>
</NavLink>
)}
<NavLink to="/login" onClick={handleLogout}>
<img src="/logout.png" alt="Logout Icon" />
<span>로그아웃</span>
</NavLink>
<NavLink to="/developer">
<img src="/contect.png" alt="Developer Icon" />
<span>개발자 컨텍</span>
</NavLink>
</Sidebar>
<Outlet />
</Wrapper>
);
}
useState :
상태 관리를 위한 훅
데이터를 저장하고 업데이트 하는데 사용
const [현재 상태 값, 업데이트 할 상태 값] = useState(초기값);
useEffect :
사이드 이펙트를 처리하기 위한 훅
useEffect(() => {
// 실행할 동작
return () => {
// 정리(clean-up) 동작 (선택 사항) };
},
[dependencyArray]);
의존성 배열 : 배열에 포함된 값이 변경될 때만 useEffect가 실행, 생략하면 매 렌더링마다 실행, 비우면 마운트 시 한 번만 실행
728x90
반응형
'웹개발 포트폴리오' 카테고리의 다른 글
[개인 포트폴리오] [클라이밍 커뮤니티 SNS] 2. 코드 분석 <login.js> (0) | 2024.12.20 |
---|---|
[개인 포트폴리오] [클라이밍 커뮤니티 SNS] 2. 코드 분석 <protected-route.js> (0) | 2024.12.20 |
[개인 포트폴리오] [클라이밍 커뮤니티 SNS] 2. 코드 분석 <App.js> (0) | 2024.12.20 |
[개인 포트폴리오] [클리이밍 커뮤니티 SNS] 1. 구상 및 완성 과정 (0) | 2024.12.19 |
[팀 포트폴리오] [Momentum 클론 웹사이트] 2. 코드 분석 <App.css> (0) | 2024.12.11 |