์ต์ข ๊ตฌํ ๋ชจ์ต
JSX ์ฝ๋ ๋งํฌ์ ๊ตฌ์กฐ
์ด๋ฒ ํ๋ก์ ํธ์์ ๋ง์ดํ์ด์ง๋ฅผ ๊ตฌํํ๋ฉด์ ์กฐ๊ธ ์ ๋ฅผ ๋จน์๋ ๋ถ๋ถ์ด ์๋๋ฐ, ์ธ๋ถ ๋ค๋น๊ฒ์ด์ ๋ฐ์์ ๋ง์ดํ์ด์ง ์์ ๋ฉ๋ด ํญ์ผ๋ก ๊ตฌํํ๋ ๋ด ํ๋กํ, ๋ด ๋ ์ํผ, ๋ด ์ข์์, ๋ฐ์ ๋๊ธ ๋ค๊ฐ์ ํญ์ ๊ฐ๊ฐ ํ๋์ฉ ๋ค๋ฅธ ํ์ด์ง์ฒ๋ผ ์ ๊ทผํ ์ ์๊ฒ ๋ง๋๋ ๊ฒ์ด์๋ค.
์ฒ์์๋ useState๋ฅผ ์ด์ฉํด์ ์ํ๋ก ์ฒ์ currentTab์ 0์ผ๋ก ๋๊ณ , ํ์ฌ ๋๋ฌ์ง ํญ์ด currentTab์ด ๋๋๋ก ๊ตฌํํ๋๋ฐ, ์ด๋ ๊ฒ ํ๋๋ ๋ง์ดํ์ด์ง์ ๋ค์ด์ค๋ฉด ๋ฌด์กฐ๊ฑด ์ํ๊ฐ 0๋ฒ์งธ์ธ ๋ด ํ๋กํ๋ก ์์์ด๋๊ณ , ์ธ๋ถ์์ ๋ง์ดํ์ด์ง ๊ฐ๊ฐ์ ํญ์ ์ ๊ทผํ ์ ์๋ค๋ ๋ฌธ์ ์ ์ด ์์๋ค.
๊ธฐ์กด ์ฝ๋
<Menu className="menu">
{menuArr.map((menu, idx) => (
//๊ธฐ์กด menuTab์ useParams ์ ์ฉ ์ด์
// <Li
// key={idx}
// onClick={() => selectMenuHandler(idx)}
// isFocused={idx === currentTab}
// >
// {menu.name}
// </Li>
))}
</Menu>
๊ฒฐ๋ก ์ ์ผ๋ก๋ ๋ฉ๋ดํญ์ useParams๋ก ๊ด๋ฆฌํ์ฌ ๋ผ์ฐํ ์ฃผ์๊ฐ์ ์ฃผ๋ฉด ๊ฐ๊ฐ์ ํญ์ด ๋ค๋ฅธ ํ์ด์ง์ฒ๋ผ ๋ณด์ด๊ฒ๋์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐ ํ ์ ์์๋ค.
๋จผ์ ๋ฉ๋ด ํญ์ด ๋ <Menu> ์ปดํฌ๋ํธ์ ์ํด์๋ ์์ ๋ค๊ฐ๋ฅผ menuArr ์ด๋ผ๋ ๋ฐฐ์ด์ ๋ด์์ฃผ์๋ค.
name์๋ ํญ ๋ฉ๋ด์ ๋ฐํ liํ๊ทธ์ ์ด๋ฆ, title์๋ <MenuTitle> ์ ๋์ฌ ์ ๋ชฉ, content์๋ <MenuContent>์ ์ค์ ๋ก ๋ฐ ์ปดํฌ๋ํธ๋ฅผ ๋ด์๋ค.
const { id } = useParams();
const menuArr = [
{
name: "๋ด ํ๋กํ",
title: "",
content: <MyProfile />,
id: 0,
},
{
name: "๋ด ๋ ์ํผ",
title: "๋ด๊ฐ ์์ฑํ ๋ ์ํผ",
content: <MyRecipeBox />,
id: 1,
},
{
name: "๋ด ์ข์์",
title: "๋ด๊ฐ ์ข์ํ ๋ ์ํผ",
content: <MyRecipeLikedBox />,
id: 2,
},
{
name: "๋ฐ์ ๋๊ธ",
title: "๋ด๊ฐ ๋ฐ์ ๋๊ธ",
content: <CommentsBox />,
id: 3,
},
];
๊ตฌ์กฐ ๋ถํดํ ๋น์ผ๋ก ๋ด์ id๋ useParams์์ ํ๋ผ๋ฏธํฐ๋ก ์ฆ, ๋งค๊ฐ๋ณ์๋ก ์ฐ์ผ ๊ฐ์ ์ง์ ํด์ค ๊ฒ์ด๋ค.
๊ฐ๊ฐ์ ๋ฉ๋ดํญ์ id ๋ก 0, 1, 2, 3 ์ ์ฃผ๊ณ ๋ฉ๋ด ํญ์ ๋๋ฅผ๋๋ง๋ค ๋ผ์ฐํ ์ฃผ์๊ฐ์ด 0 ,1, 2, 3 ์ผ๋ก ๋ฐ๋๊ฒ ๋ง๋๋ ค๋ ๋ชฉ์ ์ด๋ค.
JSX ์ฝ๋
๋ฆฌํด๋ถ๋ถ์ ๋ณด๋ฉด, ํญ ๋ฉ๋ด๊ฐ ๋ค๊ฐ์ง๊ฐ ๋์ค๋ Menu ์ปดํฌ๋ํธ์๋ Li ํ๊ทธ๋ก ๊ด๋ฆฌํ์ฌ menuArr ๋ฐฐ์ด์ map์ผ๋ก ๋๋ ค ๊ฐ๊ฐ menu.id ๊ฐ์ผ๋ก ์ฐ๊ฒฐ๋๋๋ก ํ์๋ค. ๋๋ฅด๋ ํญ or ๋ค๋น๊ฒ์ด์ ๋ฐ์์ ๋ค์ด์ฌ ๋ 2๋ฒ์งธ ํญ์ด๋ฉด /mypage/2 ์ด๋ฐ์์ผ๋ก ์ฐ๊ฒฐ๋๋๋ก ๋ง์ด๋ค.
์ ๋ชฉ๊ณผ ์ปจํ ์ธ ๋ถ๋ถ์ menuArr์ id๋ฒ์งธ์ title๊ณผ content๊ฐ ๋๋๋ก ์ฝ๋ ์์ฑํ๋ค.
return (
<MenuTabContainer>
<Menu className="menu">
{menuArr.map((menu, idx) => (
<Li key={idx} isFocused={String(idx) === id}>
{/* ํญ ๋ฉ๋ด ์์์ ๋งํฌ๋ฌ๊ธฐ */}
{/* ๋งํฌ๋ ์ปดํฌ๋ํธ ํญ ์์์๋ ์ปจํ
ํธ ์ฐ๊ฒฐ */}
<Link to={`/mypage/${menu.id}`}>{menu.name}</Link>
</Li>
))}
</Menu>
<MenuTitle>
{menuArr[id].title}
</MenuTitle>
<MenuContent className="MenuContent">
{menuArr[id].content}
</MenuContent>
</MenuTabContainer>
);
๐ก
์ฌ๊ธฐ์ ๋ด๊ฐ ํค๋งธ๋ ๋ถ๋ถ ํ ๊ฐ์ง๋ฅผ ๋ ์ถ๊ฐํ์๋ฉด,
Li ํ๊ทธ์ ๋ณด๋ฉด isFocused ๋ผ๋ props๊ฐ ์๋๋ฐ ์ด๊ฑด Li ์์๊ฐ ๊ฐ์ง๊ณ ์๋ ์์ฒด idx ์ useParams๊ฐ ๊ฐ์๋๋ง css๋ฅผ ์งํ ๋ฏผํธ์์ผ๋ก ๋ํ๋ด๋ ์ฝ๋์ด๋ค.
์ฒ์์ isFocused={idx === id}
์ด๋ ๊ฒ ์์ฑํ์๋๋ฐ, ๋ค๊ฐ์ ๋ฉ๋ดํญ Li ์์๊ฐ ๋ชจ๋ ์งํ ๋ฏผํธ์์ผ๋ก ์ฑ์์ง๋๊ฒ ์๋๊ฐ..? ๋์ดด..
์๊ณ ๋ณด๋, ๊ฐ์ฅ ๊ธฐ๋ณธ์ ์ธ๊ฑธ ๋์ณค๋๋ฐ, useParams๋ก ๋ฐ๋ id๋ ์ซ์๊ฐ ์๋ ๋ฌธ์ํ์ด๋ค!
๋ฐ๋ผ์, map์์ ๋๋ฆฌ๋ idx์ธ ์ซ์ํ์ String์ผ๋ก ๋ณํํด์ฃผ๋ฉด ๋ฐ๋ก! ํด๊ฒฐ๋ ๋ฌธ์ ์๋ค.
//MenuTabStyle.js
export const Li = styled.li`
width: calc(90% / 4); //li ์ฐจ์ง๊ณต๊ฐ 90%๋กํ๊ณ ์์ ์ปดํฌ๋ํธ์์ ๊ฐ๊ฒฉ ๋์ฐ๋ ค๊ณ
display: flex;
height: 40px;
cursor: pointer;
border-radius: 35px;
justify-content: center;
align-items: center;
background-color: var(--mint-300);
&:hover {
background-color: var(--mint-500);
color: white;
box-shadow: var(--red-050) 0px 10px 20px, var(--red-100) 0px 6px 6px;
}
${({ isFocused }) =>
isFocused &&
css`
background-color: var(--mint-500);
box-shadow: rgba(0, 0, 0, 0.19) 0px 10px 20px, var(--red-075) 0px 6px 6px;
`}
`;
App.js์ ๋ง์ด ํ์ด์ง๋ฅผ ๋ผ์ฐํ ํ ์ฃผ์๋ฅผ ์๋์ ๊ฐ์ด ์ ์ด์ฃผ์๋ค.
/mypage/0 ์ด๋ฐ์์ผ๋ก ์ฃผ์๋ฅผ ์น๋ฉด ๋ ๋๋งํ๋ ์ปดํฌ๋ํธ๋ <MenuTab> ์ปดํฌ๋ํธ๋ฅผ ํฌํจํ๊ณ ์๋ <MyPage> ์ปดํฌ๋ํธ์ด๋ค.
App.js์๋ useParams๋ฅผ import ํด์์ผ๋๋๊ฑด์ง..? ํท๊ฐ๋ ธ์ง๋ง ์ํด์ค๋ ์๋ ์ฝ๋๋ง ๋ฃ์ผ๋ฉด ์ ์๋ํ์๋ค.
//App.js
import {
BrowserRouter,
Routes,
Route,
} from "react-router-dom";
...์๋ต
import MyPage from "./pages/MyPage/MyPage";
function App() {
return (
<BrowserRouter>
<GlobalStyle />
<Gnb />
<Routes>
...์๋ต
<Route path="/mypage/:id" element={<MyPage />} />
</Routes>
</BrowserRouter>
);
}
export default App;
์์ฑ ์ฝ๋
//MenuTab.js
import { Link, useParams } from "react-router-dom";
import CommentsBox from "../MyCommentsBox/CommentsBox";
import MyProfile from "../MyProfile/MyProfile";
import MyRecipeBox from "../MyRecipeBox/MyRecipeBox";
import MyRecipeLikedBox from "../MyRecipeLikedBox/MyRecipeLikedBox";
import {
MenuTabContainer,
Menu,
Li,
MenuTitle,
MenuContent,
} from "./MenuTabStyle";
const MenuTab = () => {
const { id } = useParams();
// console.log("usParmas์์ด๋๊ฐ", id);
const menuArr = [
{
name: "๋ด ํ๋กํ",
title: "",
content: <MyProfile />,
id: 0,
},
{
name: "๋ด ๋ ์ํผ",
title: "๋ด๊ฐ ์์ฑํ ๋ ์ํผ",
content: <MyRecipeBox />,
id: 1,
},
{
name: "๋ด ์ข์์",
title: "๋ด๊ฐ ์ข์ํ ๋ ์ํผ",
content: <MyRecipeLikedBox />,
id: 2,
},
{
name: "๋ฐ์ ๋๊ธ",
title: "๋ด๊ฐ ๋ฐ์ ๋๊ธ",
content: <CommentsBox />, //์๊ฐ ๋ณํ ํจ์ ๋ด๋ ค์ฃผ๊ธฐ
id: 3,
},
];
// console.log(menuArr);
return (
<MenuTabContainer>
<Menu className="menu">
{menuArr.map((menu, idx) => (
<Li key={idx} isFocused={String(idx) === id}>
{/* ํญ ๋ฉ๋ด ์์์ ๋งํฌ๋ฌ๊ธฐ */}
{/* ๋งํฌ๋ ์ปดํฌ๋ํธ ํญ ์์์๋ ์ปจํ
ํธ ์ฐ๊ฒฐ */}
<Link to={`/mypage/${menu.id}`}>{menu.name}</Link>
</Li>
))}
</Menu>
<MenuTitle>
{menuArr[id].title}
</MenuTitle>
<MenuContent className="MenuContent">
{menuArr[id].content}
</MenuContent>
</MenuTabContainer>
);
};
export default MenuTab;
๋๊ตฐ๊ฐ์๊ฒ ๋์์ด ๋๊ธธ ๋ฐ๋ผ๋ฉฐ..!
'React' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
npm install -g ์๋ฌ EACCES (1) | 2023.01.05 |
---|---|
๋ฆฌ์กํธ App.js useEffect ๋น๋๊ธฐ ํธ์ถ์์ ์ด์ ํด๊ฒฐ Suspense lazy (0) | 2022.11.30 |
ํ๋ก ํธ์๋ ๊ธฐ์ ๋ฉด์ ๊ธฐ์ด ์์์ง๋ฌธ ๋ต๋ณ ์ ๋ฆฌ (0) | 2022.11.27 |
๋ฆฌ์กํธ react-hook-form input ๋น์ด์์ ๋ button disabled ์ ์ฉ (0) | 2022.10.31 |
VSCode ํน์ ๊ธ์ ์ ๋ณ๊ฒฝ (0) | 2022.10.12 |