코딩기록

vscode로 리액트 타입스트립트 프로젝트 만들기2 - 서비스 만들기 메인 코드 본문

프론트/리액트

vscode로 리액트 타입스트립트 프로젝트 만들기2 - 서비스 만들기 메인 코드

뽀짝코딩 2025. 2. 7. 21:42
728x90

 

 

[ Header.tsx ]

import React from 'react';
import styled from 'styled-components';
import { ProgressBar } from 'react-bootstrap';

interface Props {
  type: string;
}

export default function Header(props: Props) {
  return (
    <>
      {props.type === 'progress' ? (
        <ProgressWrapper>
          <ProgressBar now={60} label={`${60}%`} style={{ width: '100%', height: '30px' }} />
        </ProgressWrapper>
      ) : (
        <TitleWrapper>😻예비집사 판별기</TitleWrapper>
      )}
    </>
  );
}

const ProgressWrapper = styled.div`
  font-size: 40pt;
  align-items: center;
  display: flex;
  justify-content: center;
  font-family: 'Jalnan';
  padding: 20px 20px 20px 20px;
`;
const TitleWrapper = styled.div`
  background: #ffa07a;
  font-size: 40pt;
  align-items: center;
  display: flex;
  justify-content: center;
  font-family: 'Jalnan';
  padding: 20px 20px 20px 20px;
`;

 

 

[ MainPage.tsx ]

import React from 'react';
import styled from 'styled-components';
import { Button, Image } from 'react-bootstrap';
import { useNavigate } from 'react-router-dom';

import BabyDogImg from '../assets/babyDog.jpg';
import Header from '../components/Header';

export default function MainPage(): React.ReactElement {
  const navigate = useNavigate();

  const handleClickButton = () => {
    navigate('/question');
  };

  return (
    <>
      <Wrapper>
        <ContentsWrapper>
          <Header type="title" />
          <Title>나에게 맞는 주인님은?</Title>
          <LogoImage>
            <Image className="rounded-circle" src={BabyDogImg} width={300} height={300} />
          </LogoImage>
          <Desc>MBTI를 기반으로 하는 나랑 잘맞는 고양이 찾기!</Desc>
          <Desc>내가 집사가 되서 고양이를 키운다면..?</Desc>
          <Button
            className="btn-danger"
            onClick={handleClickButton}
            style={{ fontSize: 15, marginTop: 20, marginBottom: 20 }}>
            테스트 시작하기
          </Button>
        </ContentsWrapper>
      </Wrapper>
    </>
  );
}

const Wrapper = styled.div`
  display: flex;
  flex-direction: column;
  width: 100%;
  height: 100vh;
  background: #fffacd;
  font-family: 'Jalnan';
`;

const ContentsWrapper = styled.div`
  align-items: center;
  display: flex;
  justify-content: center;
  flex-direction: column;
  margin-top: 20px;
`;
const Title = styled.div`
  margin-top: 20px;
  font-size: 10pt;
`;
const LogoImage = styled.div`
  width: 200;
  height: 200;
  margin-top: 10px;
  margin-bottom: 20px;
`;

const Desc = styled.div`
  font-size: 10pt;
`;

 

 

[ QuestionPage.tsx ]

import React from 'react';
import styled from 'styled-components';
import { Button } from 'react-bootstrap';

import { QuestionData } from '../stores/Questions/QuestionData';
import Header from '../components/Header';

export default function QuestionPage(): React.ReactElement {
  return (
    <Wrapper>
      <Header type="progress" />
      <ContentsWrapper>
        <Title>{QuestionData[0].title}</Title>
        <ButtonGroup>
          <Button>{QuestionData[0].answera}</Button>
        </ButtonGroup>
        <Title>{QuestionData[0].title}</Title>
        <Button>{QuestionData[0].answerb}</Button>
      </ContentsWrapper>
    </Wrapper>
  );
}

const Wrapper = styled.div`
  display: flex;
  flex-direction: column;
  width: 100%;
  height: 100vh;
  background: #fffacd;
  font-family: 'Jalnan';
`;

const ContentsWrapper = styled.div`
  align-items: center;
  display: flex;
  justify-content: center;
  flex-direction: column;
  margin-top: 20px;
`;

const Title = styled.div`
  margin-top: 20px;
  font-size: 10pt;
`;

const ButtonGroup = styled.div`
  display: flex;
  flex-direction: column;
  justify-content: center;
`;

 

Header.tsx 페이지를 만들고 export해서 props로 보낸다.

헤더가 필요한 곳에서는 

import를 해서 받고 <Header type=" " /> type으로 쓴다.

여기서는 'progress'라는 문자열이 있는 곳에서 title을 보여주고 아닌 곳에선 title을 보여준다.

 

 

 

페이지 이동- 라우팅

[ app.tsx ]

import React from 'react';
import './App.css';

import { BrowserRouter, Route, Routes } from 'react-router-dom';

import MainPage from './pages/MainPage';
import Question from './pages/QuestionPage';
import Result from './pages/ResultPage';

function App(): React.ReactElement {
  return (
    <BrowserRouter future={{ v7_relativeSplatPath: true }}>
      <Routes>
        <Route path="/" element={<MainPage />} />
        <Route path="/question" element={<Question />} />
        <Route path="/result" element={<Result />} />
      </Routes>
    </BrowserRouter>
  );
}

export default App;

App.tsx는 라우팅 설정을 담당하는 컴포넌트다. 여기 적힌 "/" url 경로에 따라 보여주는 컴포넌트가 결정된다.

즉, url 요청에 따라 페이지 이동이 이뤄진다.

 

  • 라우팅 설정 (BrowserRouter, Route, Routes)
    • BrowserRouter: 브라우저에서 URL을 관리하는 React Router의 래퍼 컴포넌트. 이 컴포넌트를 사용하면 URL에 따라 어떤 컴포넌트를 렌더링할지 설정. 즉, 라우팅 기능을 제공하는 역할.
    • Routes: 여러 개의 Route 컴포넌트를 감싸는 컨테이너. 이곳에 정의된 경로에 맞는 컴포넌트를 렌더링.
    • Route: 각 URL 경로에 대해 어떤 컴포넌트를 보여줄지 정의하는 컴포넌트. 예, / 경로에 대해 MainPage, /question 경로에 대해 Question, /result 경로에 대해 Result 컴포넌트를 렌더링.
  • 컴포넌트 렌더링
    • element={<MainPage />}와 같은 방식으로 각 경로에 대응하는 컴포넌트를 지정. Routes는 URL 경로에 맞는 컴포넌트를 선택하여 렌더링.

 


src/stores/Questions/types.ts  는 타입을 관리하는 파일이다.

 

[ types.ts ]

export interface IQuestion {
  id: number;
  title: string;
  answera: string;
  answerb: string;
  type: string;
}

 

[ QuestionData.tsx ]

import { IQuestion } from './types';

export const QuestionData: IQuestion[] = [
  {
    id: 1,
    title: '새로운 고양이를 데려왔다! 나의 반응은?',
    answera: '머해? 이름은 뭐로 해줄까? 자꾸 말을 걸고 싶다.',
    answerb: '혼자만의 시간이 필요하지? 적응할 시간을 준다.',
    type: 'EI',
  },
  {
    id: 2,
    title: '고양이에 대한 모든 것이 궁금해졌다. 나의 행동은?',
    answera: '고양이 관련 커뮤니티에 들어 다른 집사님들과 소통을 하며 고양이에 대한 지식을 쌓는다.',
    answerb: '커뮤니티에 가입은 하지만 눈으로 참고만 하고 혼자 찾아보는게 편하다.',
    type: 'EI',
  },
  {
    id: 3,
    title: '아무리봐도 우리 고양이가 정말 이쁜 것 같다. 나의 행동은?',
    answera:
      "'옴팡이 너무 이쁜 것 같아.. 사람들한테 자랑해야지..!!'하며 인스타를 만들어서 사진도 공유하고 소통도 한다.",
    answerb: '우리 고양이 너무 이쁘다.. 사진찍어서 사진첩에 간직한다.',
    type: 'EI',
  },
];

 

types.ts > QuestionData.ts > QuestionPage.tsx > Header.tsx > App.tsx 이렇게 사용한다.

 

 

 

 

 

 

 

 

 

참고

기억 휘발 방지용 개인 기록 블로그 입니다.  설정 패키지는 쳇지피티가 잘 압니다.

 

반응형
Comments