간단한 페이지에 user 이름을 입력해야 게시글을 볼 수 있는 인증 라우터를 만들어보자!
기본 구조는
메인 컴포넌트, home, about, posts ( post1, post2 ) 등등 이다.
이전 게시글의 업데이트 버전이므로 구조가 이해가 안된다면 참고하기!
function Snippet() {
return (
<Router>
<AuthProvider>
<nav>
<ul>
<li><Link to="/">Home</Link></li>
<li><Link to="/about">About</Link></li>
<li><Link to="/posts">Posts</Link></li>
</ul>
</nav>
<AuthStatus />
<Routes>
<Route path="/" element={<Home />} />
<Route path="about" element={<About />} />
<Route path="posts" element={<Posts />} />
<Route path="post/:postId" element={
<AuthRequired>
<Post />
</AuthRequired>
} />
<Route path="*" element={<NotFound />} />
</Routes>
</AuthProvider>
</Router>
)
}
추가 된건 아래 3가지이다.
라우터 안의 엘리먼트들을 AuthProvider로 감싸 줌
user의 이름을 입력한 상태인지 알려줄 AuthStatus 추가
그리고 유저의 이름을 입력해야지 post를 볼 수 있도록 post 엘리먼트를 AuthRequired로 감싸줌
그럼 저 세가지 컴포넌트를 만들어보자!
user의 값이 있을 때 post를 랜더링 할거기 때문에 user의 값이 있는지 없는지 파악해야 한다. useContext를 이용할 거다.
그리고 useState도 사용해주어, user의 값이 생겼을 때 업데이트 해주어야한다.
최초의 값은 null이다 아래 엘리먼트들이 이 정보를 이용할 수 있도록 준비해두었다.
const AuthContext = createContext();
function AuthProvider({ children }) {
const [user, setUser] = useState(null);
const value = { user, setUser };
return (
<AuthContext.Provider value={value}>
{children}
</AuthContext.Provider>
)
}
이제 위에서 보내준 값에 따라 로그인 되었는지, 아닌지를 표시해주자.
user의 값이 있다면 Hi! user를 표시하고, 없으면 Not logged ind을 표시할 수 있도록 삼항 연산자를 사용하였다.
처음 값이 null이면 false로 간주해 두번째 표현식인 로그아웃 상태 표시를 해주고,
user에 어떤 문자열 값이 오면 true로 간주해 첫번째 표현식이 실행된다.
function AuthStatus() {
//value 객체에 접근
const { user, setUser } = useContext(AuthContext);
return user ? (
//유저 로그인한 상태일 경우(= user가 있을 경우) 뜨는 횐영 메시지
<p>
Hi, {user} ! {" "}
<button onClick={() => setUser(null)}>Log out</button>
</p>
) : (
//로그아웃 상태 표시
<p>Not logged in</p>
)
}
이제 post 페이지를 들어갔을 때 유저가 null 상태면 로그인 폼을 반환하고,
유저 값이 있다면 post의 게시글을 보여주자.
input에 onChange를 활용하여 user이름을 제출할 수 있도록 하였다.
function AuthRequired({ children }) {
const { user, setUser } = useContext(AuthContext);
const [username, setUsername] = useState("");
function handlesubmit(e) {
e.preventDefault(); //서버에 요청하지 않도록
setUser(username);
}
//로그아웃 상태인 경우(=유저가 없을 경우) 로그인 폼 반환
if (!user) {
return (
<form onSubmit={handlesubmit}>
<h1>Login</h1>
<input
type="text"
name="username"
onChange={(e) => setUsername(e.target.value)}
required
/>
<button type="submit">Login</button>
</form>
)
}
//로그인 중인경우(user가 있는 경우) 자식 컴포넌트를 반환
return children;
}