์ ์ผ ๊ณจ์นซ๋ฉ์ด๋ฆฌ์๋ ๋ ์....๊ทธ๋๋ ๋ง์นจ๋ด ํด๊ฒฐํ๋ค๐
EXPIRED_TOKEN
์ด๋ฉด โํ ํฐ์ด ๋ง๋ฃ๋์์ต๋๋คโ๋ผ๋ ๋ฌธ๊ตฌ๊ฐ ๋ด๊ธด ๋ชจ๋ฌ์ฐฝ์ ๋์์ค๋ค.์
๋ ฅ๋ฐ์ ๋๋ค์์ ๋ด์์ ๋ฐฑ์๋์ put ์์ฒญ์ ๋ณด๋ด๊ณ ์๋ฌ๊ฐ ์์ ๊ฒฝ์ฐ throw error
๋ฅผ ํด์ค๋ค.
โญ๏ธ throw error
๋ฅผ ํ์ง ์์ผ๋ฉด ์์์ ์๋ฌ๋ฅผ ์ ๋๋ก ์ฒ๋ฆฌํ ์ ์๋ค.
const putNickName = async () => {
try {
const res = await axios.put(
"https://server.bageasy.net/members/nickname",
{
nickname: nickname,
},
{
headers: {
Authorization: token,
},
},
);
return res.data;
} catch (err) {
console.log(err);
throw err; // ์ค์!! ์ด๊ฑฐ ์ ๋ฃ์ผ๋ฉด ์๋ฌ ๊ฐ์ง๋ชปํจ
}
};
putNickName์ ์คํํด์ error๋ฅผ ์บ์นํด ์๋ฌ ์ฝ๋๊ฐ "EXPIRED_TOKEN"์ผ ๊ฒฝ์ฐ setIsExpired(true)
๋ก ์ค์ ํด์ค๋ค.
(์๋์์ isExpired๊ฐ true์ผ ๊ฒฝ์ฐ ํ ํฐ ์ฌ๋ฐ๊ธ ๋ชจ๋ฌ์ฐฝ์ ๋์ฐ๋๋ก ์ค์ ํด๋์๋ค.)
const PutNickName = async () => {
if (nickname.length < 2) {
setIsFocused(true);
} else {
try {
const data = await putNickName(); // ๋๋ค์ put ์์ฒญ
setIsOverlap(false);
setIsFocused(false);
setTemp("");
navigate("/home");
} catch (err) {
if (err.response && err.response.data.code === "EXPIRED_TOKEN") {
// ํ ํฐ ๋ง๋ฃ
setIsExpired(true);
} else if (
err.response &&
err.response.data.code === "DUPLICATE_NICKNAME"
) {
// ๋๋ค์ ์ค๋ณต
setIsOverlap(true);
setIsFocused(true);
setTemp(nickname);
}
}
}
};
ํ ํฐ ์ฌ๋ฐ๊ธ ๋ชจ๋ฌ์ฐฝ์์ ์ฌ๋ฐ๊ธ ๋ฒํผ์ ํด๋ฆญํ๋ฉด ํ์ฌ access token์ ๋ฐฑ์๋๋ก ๋ณด๋ธ๋ค.
// ํ ํฐ ์ฌ๋ฐ๊ธ
const RefreshToken = async () => {
try {
const res = await axios.post(
"https://server.bageasy.net/auth/reissue",
{},
{
headers: {
Authorization: `Bearer ${token}`,
},
},
);
console.log(res);
if (res.status == 200) {
// ํ ํฐ์ด ์ฑ๊ณต์ ์ผ๋ก ๋ฐ๊ธ๋ ๊ฒฝ์ฐ
localStorage.setItem("bagtoken", res.data.accessToken); // ํ ํฐ ์ ์ฅ
handleNavigateHome(); // ๋ฉ์ธ ํ์ด์ง๋ก ์ด๋
window.location.reload(); // ์๋ก๊ณ ์นจ
}
if (res.status == 401) {
// refresh token๋ ๋ง๋ฃ๋ ๊ฒฝ์ฐ -> ๋ค์ ๋ก๊ทธ์ธ ํ๋๋ก
localStorage.clear(); // ์ ์ฅ๋์ด ์๋ ํ ํฐ ์ญ์
handleNavigateLogin(); // ๋ก๊ทธ์ธ ํ์ด์ง๋ก ์ด๋
window.alert("ํ ํฐ์ด ๋ง๋ฃ๋์ด ์๋์ผ๋ก ๋ก๊ทธ์์ ๋์์ต๋๋ค.");
}
} catch (err) {
console.log(err.response);
}
};
import styled from "styled-components";
import Arrow from "../assets/GoogleLogin/arrow.png";
import { useNavigate } from "react-router-dom";
import { useState, useEffect, useRef } from "react";
import TokenRefreshModal from "../components/Common/TokenRefreshModal";
import axios from "axios";
const Nickname = () => {
const [nickname, setNickName] = useState(""); // ๋๋ค์ ์
๋ ฅ๋ฐ๊ธฐ
const [isOverlap, setIsOverlap] = useState(false); // ๋๋ค์ ์ค๋ณต ์ฒดํฌ
const [isFocused, setIsFocused] = useState(false); // focus ์ฌ๋ถ
const [temp, setTemp] = useState(""); // ํ์ฌ ์
๋ ฅ๊ฐ์ด ์ค๋ณต๋๋์ง ์ฒดํฌ
const [isExpired, setIsExpired] = useState(false);
const inputRef = useRef(null); // focus ๊ฐ์ง
const navigate = useNavigate();
const token = localStorage.getItem("bagtoken");
const handleNavigateBack = () => {
navigate(-1);
};
const handleNickName = e => {
setNickName(e.target.value);
};
// focus ์ฌ๋ถ ๊ฐ์ง
useEffect(() => {
const inputElement = inputRef.current;
inputElement.addEventListener("focus", () => setIsFocused(true));
inputElement.addEventListener("blur", () => setIsFocused(false));
return () => {
inputElement.removeEventListener("focus", () => setIsFocused(true));
inputElement.removeEventListener("blur", () => setIsFocused(false));
};
}, []);
const putNickName = async () => {
try {
const res = await axios.put(
"https://server.bageasy.net/members/nickname",
{
nickname: nickname,
},
{
headers: {
Authorization: token,
},
},
);
return res.data;
} catch (err) {
console.log(err);
throw err; // ์ค์!! ์ด๊ฑฐ ์ ๋ฃ์ผ๋ฉด ์๋ฌ ๊ฐ์ง๋ชปํจ
}
};
const PutNickName = async () => {
if (nickname.length < 2) {
setIsFocused(true);
} else {
try {
const data = await putNickName();
setIsOverlap(false);
setIsFocused(false);
setTemp("");
navigate("/home");
} catch (err) {
if (err.response && err.response.data.code === "EXPIRED_TOKEN") {
// ํ ํฐ ๋ง๋ฃ
setIsExpired(true);
} else if (
err.response &&
err.response.data.code === "DUPLICATE_NICKNAME"
) {
// ๋๋ค์ ์ค๋ณต
setIsOverlap(true);
setIsFocused(true);
setTemp(nickname);
}
}
}
};
return (
<>
{isExpired && <TokenRefreshModal />} // ๋ชจ๋ฌ์ฐฝ ๋์ฐ๊ธฐ
<NickNameContainer>
<ArrowIcon src={Arrow} onClick={handleNavigateBack} />
<Copy>๋๋ค์์ ์
๋ ฅํด์ฃผ์ธ์!</Copy>
<Copy2>์ดํ ๋๋ค์ ๋ณ๊ฒฝ์ด ๋ถ๊ฐํ๋ ์ ์คํ๊ฒ ๊ฒฐ์ ํด์ฃผ์ธ์.</Copy2>
<Container>
<Input
placeholder="์ฌ๊ธฐ์ ์
๋ ฅํ์ธ์..."
onChange={handleNickName}
ref={inputRef}
color={
isFocused &&
(nickname.length < 2 || (isOverlap && nickname === temp))
? "T"
: "F"
}
/>
{isFocused && nickname.length < 2 && (
<Copy3>- ๋๋ค์์ 2๊ธ์ ์ด์ ์
๋ ฅํด์ฃผ์ธ์.</Copy3>
)}
{isFocused && isOverlap && nickname === temp && (
<Copy3>- ์ค๋ณต๋๋ ๋๋ค์์
๋๋ค.</Copy3>
)}
</Container>
<Btn onClick={PutNickName}>ํ์ธ</Btn>
</NickNameContainer>
</>
);
};
export default Nickname;
import { styled } from "styled-components";
import ModalBg from "../../assets/modal/modal_bg.png";
import axios from "axios";
import { useNavigate } from "react-router-dom";
const TokenRefreshModal = () => {
const navigate = useNavigate();
const token = localStorage.getItem("bagtoken");
const handleNavigateHome = () => {
navigate("/home");
};
const handleNavigateLogin = () => {
navigate("/login");
};
// ํ ํฐ ์ฌ๋ฐ๊ธ
const RefreshToken = async () => {
try {
const res = await axios.post(
"https://server.bageasy.net/auth/reissue",
{},
{
headers: {
Authorization: `Bearer ${token}`,
},
},
);
console.log(res);
if (res.status == 200) {
// ํ ํฐ์ด ์ฑ๊ณต์ ์ผ๋ก ๋ฐ๊ธ๋ ๊ฒฝ์ฐ
localStorage.setItem("bagtoken", res.data.accessToken); // ํ ํฐ ์ ์ฅ
handleNavigateHome(); // ๋ฉ์ธ ํ์ด์ง๋ก ์ด๋
window.location.reload(); // ์๋ก๊ณ ์นจ
}
if (res.status == 401) {
// refresh token๋ ๋ง๋ฃ๋ ๊ฒฝ์ฐ -> ๋ค์ ๋ก๊ทธ์ธ ํ๋๋ก
localStorage.clear(); // ์ ์ฅ๋์ด ์๋ ํ ํฐ ์ญ์
handleNavigateLogin(); // ๋ก๊ทธ์ธ ํ์ด์ง๋ก ์ด๋
window.alert("ํ ํฐ์ด ๋ง๋ฃ๋์ด ์๋์ผ๋ก ๋ก๊ทธ์์ ๋์์ต๋๋ค.");
}
} catch (err) {
console.log(err.response);
}
};
return (
<Container>
<P>์ธ์ฆ ํ ํฐ์ด ๋ง๋ฃ๋์์ต๋๋ค. ๋ค์ ๋ฐ๊ธํด์ฃผ์ธ์.</P>
<Btn onClick={RefreshToken}>์ฌ๋ฐ๊ธ</Btn>
<Modal src={ModalBg} />
</Container>
);
};
export default TokenRefreshModal;