로그인 / 회원가입
이 마이페이지 / 로그아웃
으로 바뀌어 보여야 했다.const { data } = useQuery(
"userInfo",
async () => {
const response = await getUserInformation();
setUserInfor(response);
}
);
HOC(고차 컴포넌트)는 컴포넌트를 가져와 새 컴포넌트를 반환하는 함수입니다.
Enrolleds
라는 컴포넌트를 withauth
로 감싸 반환하는 식으로 구현했다.//Enrolleds
import withAuth from "@/_helpers/withauth";
import { ContentsTable } from "@/components/mypage/ContentsTable";
import ContentsTableSideBar from "@/components/mypage/ContentsTableSideBar";
import styled from "styled-components";
const Enrolleds = () => {
return (
<Container>
<InnerContainer>
<ContentsTableSideBar />
<ContentsTable />
</InnerContainer>
</Container>
);
};
export default withAuth(Enrolleds);
withAuth
는 아래와 같이 구현 돼 있다.
크게 보자면 4단계다.
- cookie에 담겨있는 accessToken을 확인
- useQuery로 api 통신하여 결과값 response 반환
- response 값을 recoil set 값으로 전달
- WrappedComponent 반환
withauth
가 props로 받아오는 컴포넌트를 말한다. 여기서는withauth
로 감싸여진Enrolleds
컴포넌트이다.
import { useRouter } from "next/router";
import { getCookie } from "./getcookie";
import { useQuery } from "react-query";
import { getUserInformation } from "./axiosapi";
import { useResetRecoilState, useSetRecoilState } from "recoil";
import { userInformation } from "../../shared/atoms";
const withAuth = (WrappedComponent: any) => {
return () => {
const Router = useRouter();
const setUserInfor = useSetRecoilState(userInformation);
const resetUerState = useResetRecoilState(userInformation);
const accessToken = getCookie("accessToken");
if (!accessToken) {
resetUerState();
}
const { data } = useQuery(["userInfo"], async () => {
const response = await getUserInformation();
setUserInfor(response);
});
return <WrappedComponent />;
};
};
export default withAuth;
if (typeof window !== "undefined") {} 을 상단에 설정했기에 hydration 오류가 났었다.
if (typeof window !== "undefined")
를 사용하여 클라이언트 브라우저에서만 코드가 실행되도록 구성합니다. 반면, 토큰이 필요한 경우에는 서버에서도 검증해야 하기 때문에 이러한 경우 HOC는 서버에서도 실행되어야 합니다.withAuth
를 쓰지 않고 직접 적용을 해본다.import { useQuery } from "react-query";
import { useResetRecoilState, useSetRecoilState } from "recoil";
import { userInformation } from "../../shared/atoms";
import { getUserInformation } from "@/_helpers/axiosapi";
import { getCookie } from "@/_helpers/getcookie";
export const useUser = () => {
const setUserInfor = useSetRecoilState(userInformation);
const resetUerState = useResetRecoilState(userInformation);
const accessToken = getCookie("accessToken");
//어디서든 쓸건데,
//유저정보가 있다면
//리코일 벨류에 저장해주고
//유저정보가 없다면
//리코일 밸류를 리셋해주고
if (!accessToken) {
resetUerState();
}
return useQuery(
["userInfo"],
async () => {
const response = await getUserInformation();
setUserInfor(response);
},
{
enabled: !!accessToken, //accessToken이 있을때만 useQuery가 동작하게 설정
}
);
};
enabled: !!accessToken를 설정한 이유
다음의 코드에는 해당 프로젝트에서 설정한 부분이 있기에 추가적으로 설정한 내용들이 있는데, 그 이유는 다음과 같다.
getUserInformation
가 401에러를 잡고 로그인을 하라고 요청하기 때문useUser로 동시접속여부까지 잡아보려 했으나, 위와같은 문제가 발생해 동시접속은 따로 잡을 수 있게 했다.
Implement Protected Routes in NextJS
고차 컴포넌트 - react 공식문서(legacy)