IBM X RED HAT AI 과정 6기 박건일
- Main.jsx
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import './index.css'
import App from './App.jsx'
createRoot(document.getElementById('root')).render(
<App />
)
- App.jsx
import React from 'react';
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import BoardList from './components/BoardList';
import Home from './components/Home';
import NaviBar from './components/NaviBar';
import CreateBoard from './components/CreateBoard';
import AuthContextPro from './components/AuthContextPro';
import Login from "./components/Login";
import SignUp from "./components/SignUp";
import MemberList from "./components/MemberList";
import EditBoard from "./components/EditBoard";
const App = () => {
return (
<AuthContextPro>
<BrowserRouter>
<NaviBar />
<Routes>
<Route path='/boardList' element={<BoardList />}></Route>
<Route path='/' element={<Home />}></Route>
<Route path='/login' element={<Login />}></Route>
<Route path='/join' element={<SignUp />}></Route>
<Route path='/memberList' element={<MemberList />}></Route>
<Route path='/board/create' element={<CreateBoard />}></Route>
<Route path='/board/edit/:id' element={<EditBoard />}></Route>
</Routes>
</BrowserRouter>
</AuthContextPro>
);
};
export default App;
- AuthContextPro.jsx
import React, { createContext, useContext,useState } from 'react';
const AuthContext=createContext();
//- 로그인 사용자 저장
//- 로그아웃 기능
//- 모든 컴포넌트에서 로그인 상태 사용 가능
const AuthContextPro = ({children}) => {
//로그인버튼 누르면 로그인한 사용자들 로컬스토리지에 저장했다(Login.jsx)
//사용자들 가져오기
const [currentUser, setCurrentUser]=useState(
JSON.parse(localStorage.getItem("currentUser")) || null,
);
const logout=()=>{
setCurrentUser(null);
localStorage.removeItem("currentUser");
};
//로그인한 사용자 정보, 로그인 상태 (로그인/로그아웃)=> 모든 컴포넌트에서 사용 가능함
return (
<AuthContext.Provider value={ {currentUser,setCurrentUser,logout }} >
{children}
</AuthContext.Provider>
);
};
export const useAuth=()=>useContext(AuthContext);
export default AuthContextPro;
- Navibar.jsx
import React from 'react';
import {Link} from "react-router-dom";
import { useAuth } from './AuthContextPro';
import { useNavigate } from 'react-router-dom';
const NaviBar = () => {
const {currentUser, logout} = useAuth();
const navigator=useNavigate();
//로그아웃함수..logout함수호출하고 기본경로로 페이지이동
const logout1=()=>{
logout();
navigator("/");
}
return (
<>
<Link to="/">홈</Link>
<Link to="/memberList">회원목록</Link>
<Link to="/boardList">게시글목록</Link>
{/* currentUser가 false이면 로그인, 회원가입 보이게 */}
{!currentUser && (
<>
<Link to="/login">로그인</Link>
<Link to="/join">회원가입</Link>
</>
)}
{/* 로그인이 되어있는 상태면 userId 와 로그아웃 버튼 보이게 */}
:{currentUser && (
<>
<span>{currentUser.userId}님</span>
<button onClick={logout1}>로그아웃</button>
</>
)}
</>
);
};
export default NaviBar;
useAuth를 호출하여 AuthContextPro에서 관리하는 데이터에 접근한다.(currentUser, logout) 가져옴
useNavigate : 로그아웃 후 홈을 돌아가기 위함 -> 로그아웃함수 호출 -> "/"경로 이동
!currentUser(비로그인 상태) : currentUser가 null 인 경우 로그인 회원가입 보임
currentUser : 로그인 상태면 userId, 로그아웃 버튼 보임
Home.jsx
import React from 'react';
const Home = () => {
return (
<div>
Home
</div>
);
};
export default Home;
- Login.jsx
import React from 'react';
import { useAuth } from './AuthContextPro';
import { useNavigate } from 'react-router-dom';
import { useState } from 'react';
const Login = () => {
const [userId, setUserId]=useState('');
const [password, setPassword]=useState('');
const navigator=useNavigate();
//useAuth함수호출
const {setCurrentUser} = useAuth();
const onSubmit2=(e)=>{
e.preventDefault();
let users=JSON.parse(localStorage.getItem("users")) || [] ;
const loginUser= users.find((user)=> user.userId === userId && user.password === password);
//로그인 성공 시 사용자 정보 로컬스토리지에 저장
if(loginUser){
setCurrentUser(loginUser);
localStorage.setItem("currentUser", JSON.stringify(loginUser))
setUserId("");
setPassword("");
navigator('/boardList');
}
else{
alert('아이디 또는 비밀번호 오류');
}
}
return (
<div>
<form onSubmit={onSubmit2}>
<h1>로그인</h1>
아이디 :<input type='text' value={userId} onChange={(e)=>setUserId(e.target.value)}></input>
비밀번호 : <input type='password' value={password} onChange={(e)=>setPassword(e.target.value)}></input>
<button type='submit'>로그인</button>
</form>
</div>
);
};
export default Login;
- SignUp.jsx
import React, { useState } from 'react';
import { useNavigate } from 'react-router-dom';
const SignUp = () => {
const [userId, setUserId]=useState('');
const [password, setPassword]=useState('');
const navigator=useNavigate();
const onSubmit1=(e)=>{
e.preventDefault();
const user={userId, password}; //입력한 값을 객체로 담음(로컬스토리지에 저장하려고)
let users=JSON.parse(localStorage.getItem("users")) || [] ;
users.push(user); //처음에는 빈배열이므로 빈배열에 푸쉬(삽입)
localStorage.setItem("users",JSON.stringify(users));
//빈배열에 추가한 userId, password를 로컬스토리지에 저장
setUserId("");
setPassword("");
navigator('/login');
}
return (
<div>
<form onSubmit={onSubmit1}>
<h1>회원 가입</h1>
아이디 :<input type='text' value={userId} onChange={(e)=>setUserId(e.target.value)}></input>
비밀번호 : <input type='password' value={password} onChange={(e)=>setPassword(e.target.value)}></input>
<button type='submit'>회원가입</button>
</form>
</div>
);
};
export default SignUp;
- MemberList.jsx
import React, { useEffect, useState } from 'react';
const MemberList = () => {
//1. 로컬스토리지에서 회원가입했을 때 저장했던 회원정보들 다 가져오기
const users= JSON.parse(localStorage.getItem("users"));
//관리자로 로그인하면 회원목록 보이고, 관리자가 아니면 안보이게 할거임
//2. 로그인한 사용자 상태 초기화
const [currentUser, setCurrentUser]= useState(null); //currentUser에 id, password속성
//3. 로컬스토리지에서 로그인했을 때 저장한 사용자 정보 가져온다.
useEffect(()=>{
const storedUser=JSON.parse(localStorage.getItem("currentUser"));
setCurrentUser(storedUser);
},[]);
return (
<div>
<h1>회원 목록</h1>
{/* 관리자로 로그인하면 회원목록 보이고 */}
{currentUser && currentUser.userId==="admin" &&
currentUser.password==="admin" ? (
<ul>
{users.length > 0 ? (
users.map((user, index) => <li key={index}>{user.userId}</li>)
) : (
<li>회원 없다</li>
)
}
</ul>
) :( //관리자가 아니면 회원목록 안보이게 할거임
<div>
<div>회원목록은 관리자만 볼 수 있습니다</div>
</div>
)
}
</div>
);
};
export default MemberList;
- BoardList.jsx
import React, { useEffect, useState } from 'react';
import { Link } from 'react-router-dom';
const BoardList = () => {
const [posts, setPosts]=useState([]);
const [currentUser, setCurrentUser]=useState(null);
useEffect(()=>{
//posts 가져오고, currentUser도 가져온다..
const storedPosts=JSON.parse(localStorage.getItem("posts")) || [];
setPosts(storedPosts);
const storedUser=JSON.parse(localStorage.getItem("currentUser")) || [];
setCurrentUser(storedUser);
},[])
const handleDelete=(id)=>{
const updated=posts.filter((post) => post.id !== id);
setPosts(updated);
//삭제 후 남겨진 데이터만 로컬스토리지에 저장 ..posts
localStorage.setItem("posts", JSON.stringify(updated));
}
return (
<div>
<h1>게시글 목록</h1>
<Link to="/board/create">글쓰기</Link>
{posts.length > 0 ? (
posts.map((post)=>(
<div key={post.id}>
<div>{post.title}</div>
{currentUser && currentUser.userId === post.writerId && (
<div>
<Link to={`/board/edit/${post.id}`}>수정</Link>
<button onClick={()=> handleDelete(post.id)}>삭제</button>
</div>
)}
</div>
))
) : (
<div>게시물 없다</div>
)}
</div>
)
}
export default BoardList;
- CreateBoard.jsx
import React, { useEffect, useState } from 'react';
import { useNavigate } from 'react-router-dom';
const CreateBoard = () => {
//1. 제목 상태 초기화
const [title, setTitle]=useState('');
//2. 내용 상태 초기화
const [content, setContent]=useState('');
//3. 네비게이트(코드내에서 페이지 이동)
const navigator=useNavigate();
//login.jsx 에서 저장한 로그인한 사용자 정보 가져온다.
const currentUser=JSON.parse(localStorage.getItem("currentUser"));
//currentUser 가 false면 alert -> 로그인 필요해
// /login
useEffect(()=>{
if(!currentUser){
alert("로그인 필요하다");
navigator('/login');
}
},[]);
//4. onSubmit1 구현 -> 새로고침 방지
const onSubmit1=(e)=>{
e.preventDefault();
//const post={id:Date.now(), title, content}
//4.1 로컬스토리지에서 내가 쓴 제목과 내용을 읽어와서 posts에 저장 / 근데 만약에 내가 쓴 제목, 내용이 없으면 []
//문자열 -> 객체로 변환
let posts=JSON.parse(localStorage.getItem("posts")) || [];
const newPost={
id:Date.now(),
title,
content,
writerId:currentUser.userId, //현재 로그인한 사용자 아이디 추가해서 배열에 삽입
}
//posts 에다 newPost추가
posts.push(newPost);
//4.2 로컬스토리지에 내가 쓴 제목과 내용을 저장 (키 이름: posts)
//어차피 getItem으로 처음에 꺼낼 데이터가 없기때문에 posts=[]
localStorage.setItem("posts", JSON.stringify(posts));
setTitle("");
setContent("");
navigator('/boardList');
};
return (
<div>
<h1>게시글 작성</h1>
<form onSubmit={onSubmit1}>
제목 : <input type='text' value={title} onChange={(e)=>setTitle(e.target.value)} />
내용 : <textarea value={content} onChange={(e)=>setContent(e.target.value)} />
<button type='submit'>작성 완료</button>
</form>
</div>
);
};
export default CreateBoard;
EditBoard.jsx
import React, { useEffect, useState } from 'react';
import { useParams } from 'react-router-dom';
import { useNavigate } from 'react-router-dom';
const EditBoard = () => {
//board/edit/${post.id} 해당하는 id가져옴
const {id} =useParams();
const [post, setPost]=useState({title:"", content:""});
const navigator=useNavigate();
useEffect(()=>{
const posts=JSON.parse(localStorage.getItem("posts")) || [];
const currentPost=posts.find((p)=> parseInt(id) === p.id);
if(currentPost){
setPost(currentPost);
}
},[id]);
const onSubmit1=(e)=>{
e.preventDefault();
let posts=JSON.parse(localStorage.getItem("posts")) || [];
posts=posts.map((p) => p.id === parseInt(id) ? {...post, writerId: p.writerId} : p);
//수정된 값 다시 로컬스토리지에 저장
localStorage.setItem("posts", JSON.stringify(posts));
//boardList로 이동
navigator('/boardList');
}
return (
<div>
<h1>게시글 수정</h1>
<form onSubmit={onSubmit1}>
<input value={post.title} onChange={(e)=>setPost({...post, title:e.target.value})}></input>
<textarea value={post.content} onChange={(e)=>setPost({...post, content:e.target.value})}></textarea>
<button>수정</button>
</form>
</div>
);
};
export default EditBoard;