🐭 설정 페이지 설명해줘

카카오 로그인을 통해 평판 등록이 가능한 유저의 상세 정보를 변경하는 페이지입니다. 추가로 카카오 로그인 유저는 국적 선택, 테두리 색상 커스텀이 가능한 옵션을 추가했습니다.
next-i18n을 사용해 다국어 지원을 할 예정이었지만 그만큼 큰 규모는 아니었고 api route로 직접 api를 만들어서 사용해 보고 싶어 해당 방식을 이용해 국적 선택에 따라 챔피언 언어가 다르게 설정했다
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
try {
const { data } = await instance.get("/champ");
if (req.query.locale == "en") {
const Data = data.map((val: Champions) => {
return val.champNameEn;
});
res.status(200).json(Data);
} else {
const Data = data.map((val: Champions) => {
return val.champNameKo;
});
res.status(200).json(Data);
}
} catch (error) {
res.status(500).json({ error: "failed" });
}
}
함수 인자에 들어가는 string 값에 따라 출력하는 api가 다르게 설정했습니다
export const useGetChampionName = (locale?: string) => {
return useQuery<IChampionName, ErrorHandle, string[]>(
["ChampName"],
() => {
return axios.get(`/api/locale?locale=${locale}`);
},
{
select: (data) => data.data,
}
);
};

페이지 컨테이너 테두리 색상을 커스텀 가능하게 했습니다. 해당 색상을 설정하면 테두리 색상과 함께 라인 애니메이션, border 색상 역시 커스텀 색상과 동일하게 설정했습니다. 색상 값은 recoil을 사용해 로컬 스토리지를 통해 전역으로 사용했습니다.
<div
className={`z-50 h-[85%] w-[80%] overflow-hidden rounded-xl bg-black bg-opacity-30 px-10 shadow-[0_0_40px_1px] ${
color === 1
? "shadow-blue-100"
: color === 2
? "shadow-[#5F99FF]"
: color === 3
? "shadow-[#00D39E]"
: color === 4
? "shadow-[#FF7637]"
: "shadow-gray-700"
}`}
></div>;
export function useShadow(atom: RecoilState<any>) {
const [isInitial, setIsInitial] = useState<boolean>(true);
const [atomName, SetAtomName] = useRecoilState(atom);
useEffect(() => {
setIsInitial(false);
}, []);
return [isInitial === true ? false : atomName, SetAtomName];
}

react-hook-form 라이브러리를 사용해 유호성 검사와 별도의 useState, onChange 함수 없이 라이브러리 옵션으로 간편하게 프로필 수정 폼을 만들었습니다. 추가로 티어, 포지션의 이미지 라디오를 구현하기 위해 css module을 수정했습니다
// react-hook-form setting
interface FormProps {
nickName: string;
position: string;
tier: string;
bio: string;
preferPosition: string;
}
const defaultValues = {
nickName: profile?.nickname,
bio: profile?.bio,
tier: String(profile?.tier),
preferPosition: profile?.preferPosition,
enableChat: profile?.enableChat,
};
const { register, handleSubmit, watch, reset } = useForm<FormProps>({
defaultValues,
});
/* 기존 radio 스타일 제거 */
input[type=radio] {
width: 0;
height: 0;
position: absolute;
left: -9999px;
}
설정 페이지로 들어왔을 때 프로필 데이터가 바로 보이지 않았던 현상이 있었습니다. 해당 이슈는 useForm에 defaultValues 옵션을 사용해 기존 데이터를 미리 가져왔고 api 값 업데이트 될 때마다 reset를 사용해 기존 데이터를 refresh 시켰습니다.
const { register, handleSubmit, watch, reset } = useForm<FormProps>({
defaultValues,
});
useEffect(() => {
if (profile) reset({ ...defaultValues });
}, [profile]);
설정 페이지에 입장하는 순간 토큰을 가지고 있는 유저의 정보를 호출하는 페이지인데 로그인하지 않은 상태에서도 api를 호출하는 건 비용적 측면에서 좋지 않다 생각해 방법을 찾던 중 현재 사용하는 react-query 라이브러리에 enable 옵션을 사용해 토큰이 없을시 api 호출 자체를 하지 않도록 설정했습니다.
const Token = getCookie("myToken") === undefined ? false : true;
export const useGetUserId = () => {
return useQuery<userOptions, ErrorHandle, userId>(
["getUserId"],
() => {
return instance.get("/user");
},
{
select: (data) => data.data,
enabled: Token,
}
);
};