Home 컴포넌트 작성
Home.jsx
는 /
경로 (기본 경로)로 접근하면 나타나는 페이지다. 일단 /login
과 /hello
링크를 생성했다.
/login
은 인증되지 않아도 접근이 가능하다/hello
는 인증된 상태여야만 접근이 가능하다 ->PrivateRoute
처리하여 인증되지 않은 상태라면/login
으로 바로 이동시킴
import React from 'react';
import { Link } from 'react-router-dom';
export default function Home() {
return (
<div className="home-wrap">
<h1>Home Sweet Home 🏠</h1>
<Link to="/login">로그인</Link>
<Link to="/hello">여긴 로그인을 해야 갈 수 있어요</Link>
</div>
);
}
지금은 로그인하지 않았기 때문에 (authenticated = false) 둘 중 어떤 것을 눌러도 모두 로그인 페이지로 넘어가게 된다.
Login 컴포넌트 작성
이제 로그인 페이지를 만들어 본다.
useState
를 이용해input
값 관리App.js
에서 전달받은handleLogin
메서드를 로그인 버튼이 클릭되면 실행
import React, { useState } from 'react';
function Login({ handleLogin }) {
const [input, setInput] = useState({});
function handleOnChage(e) {
setInput({ ...input, [e.target.name]: e.target.value });
}
function handleSubmit(e) {
e.preventDefault();
handleLogin(input);
}
return (
<div>
<form>
<input type="text" name="id" onChange={handleOnChange} />
<input type="password" name="password" onChange={handleOnChange} />
<button type="submit" onClick={handleSubmit}>LOGIN</button>
</form>
</div>
)
}
아이디와 비밀번호를 알맞게 입력한 뒤 로그인 버튼을 클릭하면, App.js
에서 auht.login()
메서드와 dispatch
가 실행되고,
로그인에 성공하면 /hello
로 이동해야한다!
PrivateRoute설정을 해주었기 때문에, /hello경로로 인증되지 않은 회원은 접근할 수 없다.
로그인에 성공해 인증을 완료하면 /hello로 redirect되도록 설정해둔 상태(PublicRoute로 감싸놨음. 사실 이건 안 해도 된다..)
문제 발생
일단 localStorage
를 사용하지 않기 때문에 발생하는 문제들이 있다.
- 로그인 후 새로 탭을 열면 또다시 로그인 해야 한다
- 탭이 여러 개인 상태에서 다른 탭에서 로그아웃해도 다른 탭은 여전히 로그인 상태
일단 다른 탭에서 로그아웃 했을 때 처리부터 해보기로 한다.
가이드에서는 로그아웃을 할 때, localStorage
에 로그아웃 기록을 남긴다.
그리고 storage
의 이벤트를 감지해서 다른 탭에서도 로그아웃이 되도록 한다. (스토리지에 이벤트 리스너를 추가할 수 있는지도 몰랐는데...!)
auth.js 수정
localStorage
에 로그아웃을 했다는 것을 기록하는 logout()
메서드를 만든다.
export function logout() {
console.log('localStorage set logout!');
window.localStorage.setItem('logout', Date.now());
}
App.js 수정
리듀서에 DELETE_TOKEN
을 추가
function reducer(state, action) {
switch (action.type) {
case 'SET_TOKEN':
return { ...state, token: action.token, authenticated: action.result };
case 'DELETE_TOKEN':
return { ...state, token: null, authenticated: false };
default:
return state;
}
}
handleLogout
메서드를 작성한다. dispatch
와 auth.logout()
을 실행
그리고 useEffect
에서 이벤트 리스너를 추가해 다른 탭에서 로그아웃 한 것을 감지한 뒤, dispatch
를 실행한다.
const handleLogout = () => {
dispatch({
type: 'DELETE_TOKEN',
});
auth.logout();
};
useEffect(() => {
window.addEventListener('storage', (e) => {
if (e.key === 'logout') {
console.log('로그아웃 감지');
dispatch({
type: 'DELETE_TOKEN',
});
}
});
}, []);
그리고 handleLogout
을 Hello
컴포넌트로 전달
<PrivateRoute
path="/hello"
authenticated={authenticated}
component={(props) => (
<Hello {...props} handleLogout={handleLogout} />
)}
/>
Hello.jsx 수정
이 컴포넌트는 인증된 회원만 접근할 수 있는 곳이므로 이곳에 로그아웃 버튼을 만든다.
import React from 'react';
export default function Hello({ handleLogout }) {
return (
<div className="hello-wrap">
<h1>로그인 성공! 🎉</h1>
<button type="button" onClick={handleLogout}>
LOGOUT
</button>
</div>
);
}
이제 다른 탭에서 로그아웃을 해도 동시에 모든 탭이 함께 로그아웃 된다!
이해 안 되는 부분은 언제든지 댓글 남겨주세요..
'STUDY > React' 카테고리의 다른 글
React | 서브라우트 Nested Route (0) | 2021.06.30 |
---|---|
React | JWT 안전하게 저장하기 (localStorage 사용 X) (3) (0) | 2021.06.02 |
React | JWT 안전하게 저장하기 (localStorage 사용 X) (1) (3) | 2021.05.27 |
React | TypeScript 반복문으로 컴포넌트 렌더 ( pass props ) (0) | 2021.04.26 |
React | TypeScript로 시작하기 (0) | 2021.04.26 |