본문 바로가기

DEVELOP

[React.js] Typescript로 초기 셋팅2 - Router 사용 하기

728x90

React 하얀 바탕에서 부터 시작(전편)은 아래 링크 참고

https://jintrue.tistory.com/entry/Reactjs-Typescript%EB%A1%9C-%EC%B4%88%EA%B8%B0-%EC%85%8B%ED%8C%85

 

[React.js] Typescript로 초기 셋팅

타입스크립트로 코드를 작성하면 오류사항이 즉각 보여 개발할 때 좀더 꼼꼼히 작업할 수 있는 이점이 있다. 확장자는 .tsx이며 Typescript로 React를 셋팅 하는 법을 기록하고자 한다. 셋팅 버전 참

jintrue.tistory.com

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. 백엔드 환경 구축 (다음 편에서 계속............)