일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
- updater
- setstate
- S3
- imagePreview
- react
- Redux
- qwe
- rendering
- 비동기
- socket.io
- routing
- FileReader
- 브라우저 렌더링
- 항해99
- previousState
- 미리보기
- CI/CD
- useEffect
- Preview
- route
- 후기
- 채팅방
- 접근 제한 라우팅
- 개발
- Github Actions
- 동기
- 7기
- 라우팅
- 배포
- 스파르타코딩클럽
- Today
- Total
삐옹
React 접근제한 라우팅 만들기 본문
상황
로그인을 하고나서 workspace 배열 내에 데이터 유무에 따라
처음 로그인한 사람(뉴비)과 기존 유저에게 다른 화면을 보여주어야 한다.
생각 할 것
앱의 상태에 따른 state 관리가 핵심이다.
- workspace 배열 내에 데이터 유무에 따라 유저의 상태를 어떻게 표현 할 것인지 명시한다.
(앱의 상태를 나타내는 state를 만든다.) - 로그인 일 때와 아닐 때를 구분한다
- 뉴비인지 아닌지 판단하는 상태를 만들기
- 로딩 중 일 떄와 아닐 때 를 구분하는 상태만들기.(스피너를 위함! 난 꼭 스피너를 넣어야겠음!)
+) 로그인 상태 유지하기
순서대로 코드로 살펴보기
상황 별 유저의 상태
// App.js
// 정리해보면 유저의 상태는 3가지로 나뉜다
// 워크스페이가 있는지 없는지 판단 중일 떄 -> "모름"
// 워크스페이가 있을 떄 -> "워크스페이스가_없는_유저"
// 워크스페이가 없을 떄 -> "워크스페이스가_있는_유저"
const APP_USER_STATE = {
UNKNOWN: "모름", // 모름 상태일 떄는 스피너가 돌 것 이다!
NEWBIE: "워크스페이스가_없는_유저",
USER: "워크스페이스가_있는_유저",
};
const App = () => { ...
}
앱의 상태를 나타내는 state를 만든다.
const App = () => {
const APP_USER_STATE = {
UNKNOWN: "모름", // 모름 상태일 떄는 뺑뻉이 스피너가 돌게한다
NEWBIE: "워크스페이스가_없는_유저",
USER: "워크스페이스가_있는_유저",
};
// 초깃값은 모름으로 해놓는다. 이때는 항상 스피너로 처리하면 될 듯
const [appState, setAppState] = useState(APP_USER_STATE.UNKNOWN);
// appState가 변경이 되면 loading 상태와 newbie인지 아닌지의 상태가 바뀐다
// appstate는 워크스페이스 리스트를 잘 받아온 뒤 NEWBIE or USER로 변경 예정
const isLoading = appState === APP_USER_STATE.UNKNOWN;
const isNewbieUser = appState === APP_USER_STATE.NEWBIE;
...
}
워크스페이스 리스트의 값에 변화가 생기면 2초 뒤 appState의 상태를 업데이트한다.
// App.js
const [appState, setAppState] = useState(APP_USER_STATE.UNKNOWN);
// ...
useEffect(() => {
setTimeout(() => {
try {
axios
.get("https://0jun.shop/api/work-spaces/lists", {
headers: {
Authorization: `Bearer ${getItemFromLs("myToken")}`,
},
})
.then((res) => {
if (res.data.success) {
const wsInfoList = res.data.includedList;
const wsList = wsInfoList.map((ws) => ws.name);
// 워크스페이스 리스트가 잘 받아와지면 appstate를 업데이트한다
// ***이때 isLoading의 상태도 자동으로 업데이트 된다***
setAppState(
wsList.length !== 0
? APP_USER_STATE.USER
: APP_USER_STATE.NEWBIE
);
}
})
.catch((error) => {
console.log(error);
});
} catch {
alert("데이터를 불러오는 도중 에러가 발생했습니다 :(");
}
}, 2000);
}, []);
로딩상태라면 스피너를 보여주고 로딩상태가 아니라면 Main 화면을 보여준다
*뉴비인지 아닌지는 Main 컴포넌트에서 가리기 위해 props로 전달한다
<Routes>
<Route path="/" element={<Login />} />
<Route path="/signup" element={<Signup />} />
// 로컬스토리지의 값에 따라 로그인이 됬으면 true 아니면 false를 반환하는 모듈을 만들었다
{isLogin() ? (
<Route
path="/main"
element={
isLoading ? (
<Spinner />
) : (
<PrivateRoute
isNewbieUser={isNewbieUser}
component={<Main />}
/>
)
}
/>
) : (
<Navigate to="/login" />
)}
</Routes>
워크스페이스 리스트에 변경이 일어나 appstate가 **변경된 후** isNewbieUser의 상태가 변경되었을 것이다.
워크스페이스가 없다면:
isNewbieUser = false 에서 isNewbieUser = true로 바뀌어서 props로 전달이 된다
워크스페이스가 있다면:
isNewbieUser = false 값 그대로 props로 전달이 된다
import React from "react";
import ScreenForNewbie from "./ScreenForNewbie";
const PrivateRoute = ({ isNewbieUser, component: Component }) => {
return <> {!isNewbieUser ? Component : <ScreenForNewbie />}</>;
};
export default PrivateRoute;
팁))
만약 isLoading이라는 값이 변경되게끔 하는 로직이 없다면??
<Route
path="/main"
element={
<PrivateRoute
isNewbieUser={isNewbieUser}
component={<Main />}
/>
}
/>
워크스페이스에 값이 들어오기 전의 isNewbieUser의 초깃값은 false이기 때문에(아래 코드 참고)
뉴비를 위한 화면이 잠깐 생겼다가 기존 유저를 위한 화면이 보이게 된다.
확실히 Loading상태가 끝나야만 뉴비화면 vs 기존유저 화면을 나눠주게끔 하는게 포인트였다.
export const APP_USER_STATE = {
UNKNOWN: "모름",
NEWBIE: "워크스페이스가_없는_유저",
USER: "워크스페이스가_있는_유저",
};
------------------------
const [appState, setAppState] = useState(APP_USER_STATE.UNKNOWN);
------------------------
const isNewbieUser = appState === APP_USER_STATE.NEWBIE;
정리
상황에 따라 다른 화면을 보여주려면
결국엔 어떤 상태에서 어떤 컴포넌트를 보여줄 것인가가 핵심이다.
접속 할 사용자가 뉴비라고 가정하고 상태들의 흐름을 다시 한번 정리해보자
화면 첫 더링 시
appState = 모름
isLoading = true => spinner 돌아가는 중..
isNewbieUser = false
useEffect 에서 워크스페이스 리스트 업데이트 후
appState = 워크 스페이스가 없는 유저
isLoading = false => Spinner 끝!
isNewbieUser = true => <ScreenForNewbie/> 렌더링
특정 경로로의 접근에 제한을 두어야 할 때
이렇게 상태들을 정의해두고 활용하는 방식은 두고두고 써먹기 좋은 것 같다
'React' 카테고리의 다른 글
리액트가 화면에 앱을 그리는 방법은 좀 다르다 (0) | 2023.06.16 |
---|---|
setState 동기로 처리해주기 (0) | 2022.07.14 |
React + Socket.io로 여러 개의 채팅방 만들기(1) (0) | 2022.07.09 |
react-datePicker 라이브러리 커스텀하기 (0) | 2022.07.08 |
[채팅 웹 사이트 구현 #1] WebSocket과 Socket.io (0) | 2022.06.26 |