연관 내용
[HOF]
[Closure]
[Local Storage]
사용되는 원리
👇🏻 컴포넌트를 함수 형태로 바꿔서 쓸 수 있다.
props는 단지 매개변수일 뿐이란 것을 알 수 있다. props 안 쓰고
asdfas
이따위로 써도 됨 ㅎㅎ
Aaa와 Bbb 사이에 컴포넌트를 추가해보자!
먼저 실행 컴포넌트를 보면, 함수 안에서 함수를 리턴하고 있다.
리턴하는 함수의 props를 리턴되는 컴포넌트에 전달해주고 있다.
Aaa를 실행시키면 Bbb 컴포넌트에 props가 전달되어서 리턴되는 것은 동일하고
먼저 실행 컴포넌트의 로직들을 실행시킬 수 있게 된다.
중간에 추가한 먼저 실행 컴포넌트를 Higher Order Component라고 부른다.
Closure로부터 확장된 개념이다.
활용: 로그인 여부 확인이 필요한 페이지에 먼저 실행할 HOC를 추가해서 useEffect로 token을 체크해줄 수 있다.
더 간단하게 바꿔보자
Bbb
로만 적어도 HOC(Bbb)가 실행된다.함수명을 with~
로 짓는 게 국룰🌟
import { useRouter } from "next/router";
import { useEffect } from "react";
// @ts-ignore
export const withAuth = (Component) => (props) => {
const router = useRouter();
/* 권한 분기 */
useEffect(() => {
if (!localStorage.getItem("accessToken")) {
alert("로그인 후 이용이 가능합니다.");
router.push("/23-04-login-check");
}
}, []);
return <Component {...props} />;
};
// prettier-ignore
export const withAuth = (Component : ComponentType) => <P extends {}>(props:P) => {
const router = useRouter();
/* 권한 분기 */
useEffect(() => {
if (!localStorage.getItem("accessToken")) {
alert("로그인 후 이용이 가능합니다.");
router.push("/23-04-login-check");
}
}, []);
return <Component {...props} /> ;
}
컴포넌트의 이름이 없어서 에러가 난다.
Component.displayName~~ 해서 붙일 수 있지만 그러려면 화살표 함수를 다시 일반 함수로 바꿔야 한다ㅠㅠ
그냥 es-lint를 잠시 꺼두자..ㅎ
eslintrc.js
rules: {
"react/display-name": "off",
},
로그인이 필요한 페이지에 1에서 만든 withAuth로 감싸서 export default하면 해당 페이지가 실행되기 전에 withAuth가 먼저 실행된다.
요로케 👉🏻 export default withAuth(LoginSuccessPage);
import { gql, useQuery } from "@apollo/client";
import { withAuth } from "../../src/components/commons/hocs/withAuth";
const FETCH_USER_LOGGED_IN = gql`
query fetchUserLoggedIn {
fetchUserLoggedIn {
email
name
}
}
`;
function LoginSuccessPage() {
const { data } = useQuery(FETCH_USER_LOGGED_IN);
return <div>{data?.fetchUserLoggedIn.name}님 환영합니다.</div>;
}
export default withAuth(LoginSuccessPage);
// withAuth가 먼저 실행된다.
// HOC의 매개변수인 Component에 LoginSuccessPage가 들어간다.