728x90
React 하얀 바탕에서 부터 시작(전편)은 아래 링크 참고
https://jintrue.tistory.com/entry/Reactjs-Typescript%EB%A1%9C-%EC%B4%88%EA%B8%B0-%EC%85%8B%ED%8C%85
8. gnb에서 페이지 이동을 위한 라우터 설정
📜Component/Header.tsx
styled-components를 이용한 태그 및 스타일 설정
framer-motion를 이용하여 gnb 클릭시 해당 페이지 active 색상 설정Link를 이용하여 클릭시 브라우저 상단 주소에 해당 페이지 이름 뜰 수 있게 설정
import { motion } from "framer-motion";
import { Link, useRouteMatch } from "react-router-dom";
import { useRecoilState } from "recoil";
import styled from "styled-components";
import { booleanState } from "../atoms";
const Inner = styled.div`
display: flex;
flex-direction: column;
gap: 32px;
align-items: center;
justify-content: center;
padding: 20px 0 28px;
border-bottom: 1px solid ${(props) => props.theme.bgColor.gray.fixth};
`;
const Row = styled.div`
position: relative;
width: 100%;
`;
const Logo = styled.div`
color: ${(props) =>props.theme.point.lavender};
font: 20px 'Righteous';
text-align: center;
`;
const Em = styled.span`
display: inline-block;
padding-left: 16px;
color: ${(props) => props.theme.point.purple};
font-size: 38px;
text-align: center;
`;
const Items = styled.ul`
display: flex;
align-items: center;
justify-content: center;
gap: 12px 38px;
`;
const Item = styled.li`
position: relative;
color: ${(props) => props.theme.textColor.gray.second};
font-size: 28px;
font-weight: 700;
line-height: 31px;
a {
&.on {
color: ${props=>props.theme.point.yellow};
}
}
`;
const Point = styled(motion.span)`
position: absolute;
width: 16px;
height: 5px;
top: -8px;
left: 0;
right: 0;
margin: 0 auto;
border-radius: 7px;
background-color: ${props=>props.theme.point.yellow};
`;
function Header(){
// Link
const homeMatch = useRouteMatch("/");
const worksMatch = useRouteMatch("/works");
const infoMatch = useRouteMatch("/info");
return (
<Inner>
<Row>
<Logo>
<Em>LOGO</Em>
</Logo>
</Row>
<Row>
<Items>
<Item>
<Link to="/" className={homeMatch?.isExact ? "on": ""}>
Intro
{homeMatch?.isExact === true && <Point layoutId="point"/>}
</Link>
</Item>
<Item>
<Link to="/works" className={worksMatch? "on": ""}>
Works
{worksMatch && <Point layoutId="point"/>}
</Link>
</Item>
<Item>
<Link to="/info" className={infoMatch? "on": ""}>
Info
{infoMatch && <Point layoutId="point"/>}
</Link>
</Item>
</Items>
</Row>
</Inner>
);
}
export default Header;
📜App.tsx
styled-components를 이용한 Reset style 설정 및 테마 설정
전역 테마 설정 소스를 이용하기 위한 버블인 atom과 recoil 이용
실제 페이지 이동을 위한 라우터 설정
라우터 설정시 "/" 메인화면의 path는 항상 하단에 존재해야한다. 그렇지 않고 상단에 두면, Works나 Info 메뉴를 클릭해도 path="/"로 모두 시작하기 때문에 path="/"에서 '/' 만 있어도 true로 간주하고 Intro 페이지로 모두 이동되어 버린다.
<Router>
<Switch>
<Route path="/works">
<Works />
</Route>
<Route path="/info">
<Info />
</Route>
<Route path="/">
<Intro />
</Route>
</Switch>
</Router>
import {BrowserRouter as Router, Switch, Route} from "react-router-dom";
import Info from "./Routes/Info";
import Works from "./Routes/Works";
import Header from "./Components/Header";
import Intro from "./Routes/Intro";
import { booleanState } from "./atoms";
import { ThemeProvider, createGlobalStyle } from "styled-components";
import { useRecoilValue } from "recoil";
import { darkTheme, lightTheme } from "./theme";
const GlobalStyle = createGlobalStyle`
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, menu, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed,
figure, figcaption, footer, header, hgroup,
main, menu, nav, output, ruby, section, summary,
time, mark, audio, video {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
font: inherit;
vertical-align: baseline;
}
/* HTML5 display-role reset for older browsers */
article, aside, details, figcaption, figure,
footer, header, hgroup, main, menu, nav, section {
display: block;
}
/* HTML5 hidden-attribute fix for newer browsers */
*[hidden] {
display: none;
}
menu, ol, ul {
list-style: none;
}
blockquote, q {
quotes: none;
}
blockquote:before, blockquote:after,
q:before, q:after {
content: '';
content: none;
}
table {
border-collapse: collapse;
border-spacing: 0;
}
* {
box-sizing: border-box;
transition: all 0.2s ease-in;
}
body {
font-weight: 300;
font-family: 'Noto Sans KR', 'Righteous';
color:${(props) => props.theme.textColor.gray.third};
line-height: 1.5;
background-color: ${(props) => props.theme.bgColor.gray.second};
}
a {
text-decoration:none;
color:inherit;
}
`;
function App() {
const themeSate = useRecoilValue(booleanState);
return (
<ThemeProvider theme={themeSate ? darkTheme : lightTheme}>
<GlobalStyle />
<Router>
<Header />
<Switch>
<Route path="/works">
<Works />
</Route>
<Route path="/info">
<Info />
</Route>
<Route path="/">
<Intro />
</Route>
</Switch>
</Router>
</ThemeProvider>
);
}
export default App;
9. 로컬 실행 잘 되나 확인
npm start
10. 백엔드 환경 구축 (다음 편에서 계속............)
'DEVELOP' 카테고리의 다른 글
[React.js] Typescript로 초기 셋팅4 - firebase 연동 및 호출 (0) | 2023.06.20 |
---|---|
[React.js] Typescript로 초기 셋팅3 - firebase로 db 붙이기(Realtime Database) (0) | 2023.06.20 |
[React.js] Typescript로 초기 셋팅 (0) | 2023.06.20 |
[CSS] 부모가 display: flex; 일때 특정 내용물 한줄로 나타내기 (0) | 2023.04.06 |
[Github] user.name, user.email 전역 변경 (0) | 2023.03.31 |