로그인 인증이후에는 로그인 한 사람과 안한 사람으로 권한 분기가 이뤄진다.
- login-check-success.tsx
export default function LoginPage(): JSX.Element { const router = useRouter(); const { data } = useQuery<Pick<IQuery, "fetchUserLoggedIn">>(FETCH_USER_LOGGED_IN); useEffect(() => { if (localStorage.getItem("accessToken") === null) { alert("로그인 후 이용 가능합니다!"); void router.push(`/section23/23-03-login-check`); } }, []); return <>WELCOME {data?.fetchUserLoggedIn.name}</>; }
특정페이지 접속 시 검사를 하고 다시 로그인으로 보내줌
페이지에서 체크를 하자!!!
✔️ 스택
상자쌓인 걸로 생각!
위에서부터 꺼내는 방법
First In Last Out FILO 필로!✔️ 큐
줄서는 것
앞에서부터 순서대로
First In First 피포!
스코프 체인이란?
해당 스코프(local)에 없으면 상위 스코프에는 있는지 스코프를 찾아 올라가는 과정을 의미한다.
클로저란?
Local 스코프의 바깥에 있는 영역으로
상위 함수와, 해당함수(여기서는 bbb함수)가 선언된 스코프 즉 상위함수를 둘러싼 환경을 말한다.
[실습]
aaa()에서 브레이크 포인트(코드를 빠르게 실행되다가 멈추고 싶은 코드를 멈추게 함)를 걸어두고 시작한다.
aaa()에 브레이크 포인트를 걸어두고 함수 안으로 하나씩 들어오니 callstack에 함수가 쌓여있다.
스코프의 글로벌 부분을 보면,
banana는 local에 있으므로 20을 출력하고,
apple은 bbb()내에 없으므로 글로벌까지 찾아 올라간 것!이런게 스코프 체인!
스코프 체인과 클로저 간단 정리❗️
- 클로저(closure) : 상위 함수 + 상위함수의 lexical enviroment(상위함수를 둘러싼 환경)
- 스코프 체인(scope chain) : 바로위 함수 스코프 뿐만아니라 global 스코프 까지 찾아 올라가는 과정
참고!
lexical scope를 공부하면 closure를 이해는데 도움이 된다.
함수를 리턴하는 함수 HOF
1️⃣aaa를 통으로 bbb라고 보고
실행하려면 aaa()()해야함.2️⃣
bbb라는 이름이 굳이 필요한가?
이름필요없음! 없애도됨!
3️⃣ 함수를 리턴하는 함수 - 화살표함수const aaa = (apple) => (banana) => { console.log(banana); console.log(apple); }; aaa(100)(500);
4️⃣
[실습] - 리액트에 적용하기
- 기존코드
const onClickPage = (event: MouseEvent<HTMLSpanElement>): void => { void refetch({ page: Number(event.currentTarget.id) }); return ( <div> {data?.fetchBoards.map((el) => ( <div key={el._id}> <span style={{ margin: "10px" }}>{el.title}</span> <span style={{ margin: "10px" }}>{el.writer}</span> </div> ))} {new Array(10).fill("a").map((_, index) => { <span key={index + 1} id={String(index + 1)} onClick={onClickPage}> {index + 1} </span>; })} </div> ); }
아이디 바인딩은 규모커질때 중복되는 문제가 될 수도 있음.
객체나 배열을 통으로도 넘길 수 있음!
event.target.id 라고 직접 입력하지 않아 코드가 짧아진다.
- 리팩토링코드
const onClickPage = (page: number) => (): void => { void refetch({ page }); }; return ( <div> {data?.fetchBoards.map((el) => ( <div key={el._id}> <span style={{ margin: "10px" }}>{el.title}</span> <span style={{ margin: "10px" }}>{el.writer}</span> </div> ))} {new Array(10).fill("철수").map((_, index) => ( <span key={index + 1} onClick={onClickPage(index + 1)}> {index + 1} </span> ))} </div> );
HOC는 Higher Order Component 개념은 위의 클로저로부터 확장된 개념으로,
상위에 있는 컴포넌트로 다른 컴포넌트보다 먼저 실행되는 컴포넌트라고 생각하자!
useEffect가 권한체크부분인데 이걸 계속해서 복붙하지 말고
권한체크컴포넌트를 따로 분리해서 만들자!
마이페이지 접속하면 App실행됨
로그인체크를 useEffect 통해서하고
return 으로 페이지가 보여짐
컴포넌트는 마이페이지와 로그인체크를 감싸고 있는 애
[권한분리실습]
- src/components/commons/hoc/withAuth.tsx
다른 컴포넌트와 함께 실행되므로 with라는 이름을 앞에 붙여준다(예: withAuth, withApollo)
import { useRouter } from "next/router"; import { useEffect } from "react"; export const LoginCheck = (Component: any) => (props: any) => { const router = useRouter(); //로그인 점검 권한체크 useEffect(() => { if (localStorage.getItem("accessToken") === null) { alert("로그인 후 이용 가능합니다!"); void router.push(`/login`); } }, []); return <Component {...props} />; };
- loginSuccessPage -> withAuth 적용하기
function LoginPage(): JSX.Element { const { data } = useQuery<Pick<IQuery, "fetchUserLoggedIn">>(FETCH_USER_LOGGED_IN); return <>WELCOME {data?.fetchUserLoggedIn.name}!!!</>; } export default LoginCheck(LoginPage);
*함수형컴포넌트형 HOC custom HOOK 이 따로 있음!