반응형
1. 환영 메시지
더보기
src/data/messages.ts
export const welcomeMessages = [
"환영합니다!",
"안녕하세요!",
"오늘도 좋은 하루 되세요!",
];
src/components/GreetingList.tsx
import { welcomeMessages } from "../data/messages";
export default function GreetingList() {
return (
<ul className="space-y-2">
{welcomeMessages.map((msg, idx) => {
return (
<li key={idx} className="p-3 bg-blue-100 rounded shadow">
{msg}
</li>
);
})}
</ul>
);
}
src/pages/GreetingPage.tsx
import GreetingList from "../components/GreetingList";
export default function GreetingPage() {
return (
<main className="min-h-screen flex flex-col items-center justify-center p-6">
<h1 className="text-3xl font-bold mb-4">👋 인사 메시지</h1>
<GreetingList />
</main>
);
}
src/App.tsx
import GreetingPage from "./pages/GreetingPage";
export default function App() {
return (
<main>
<GreetingPage />
</main>
);
}

2. 과일 상품 리스트
더보기
src/data/products.ts
export const products = [
{ id: 1, name: "딸기", price: 3000 },
{ id: 2, name: "사과", price: 2500 },
{ id: 3, name: "바나나", price: 2000 },
];
src/components/ProductItem.tsx
type Product = { name: string; price: number };
export default function ProductItem({ name, price }: Product) {
return (
<div className="border p-4 rounded shadow bg-white">
<h2 className="font-semibold">{name}</h2>
<p className="text-gray-600">{price.toLocaleString()}원</p>
</div>
);
}
src/pages/ProductListPage.tsx
import { products } from "../data/products";
import ProductItem from "../components/ProductItem";
export default function ProductListPage() {
return (
<main className="p-6 grid gap-4 grid-cols-1 sm:grid-cols-2 lg:grid-cols-3">
{products.map((item) => (
<ProductItem key={item.id} name={item.name} price={item.price} />
))}
</main>
);
}
src/App.tsx
import GreetingPage from "./pages/GreetingPage";
import ProductListPage from "./pages/ProductListPage";
export default function App() {
return (
<main>
{/* <GreetingPage /> */}
<ProductListPage />
</main>
);
}

3. 자동차 폐차 신청 폼
더보기
src/data/initialFormData.ts
export const cars = [
{ id: 1, name: "홍길동", carNum: "12가4567" },
{ id: 2, name: "이순신", carNum: "34나6677" },
{ id: 3, name: "세종대왕", carNum: "54다9999" },
];
src/components/ScrapForm.tsx
type ScrapInfo = { name: string; carNum: string };
export default function ScrapForm({ name, carNum }: ScrapInfo) {
return (
<div className="p-4 bg-white border rounded shadow">
<label htmlFor="name">이름</label>
<input id="name" type="text" value={name} />
<label htmlFor="carNum">차량번호</label>
<input id="carNum" type="text" value={carNum} />
</div>
);
}
src/pages/ApplyScrapPage.tsx
import ScrapForm from "../components/ScrapForm";
import { cars } from "../data/initialFormData";
export default function ApplyScrapPage() {
return (
<main className="flex flex-col items-center justify-center w-full">
{cars.map((car) => (
<ScrapForm name={car.name} carNum={car.carNum} />
))}
</main>
);
}
src/App.tsx
import GreetingPage from "./pages/GreetingPage";
import ApplyScrapPage from "./pages/ApplyScrapPage";
export default function App() {
return (
<main>
{/* <GreetingPage /> */}
<ApplyScrapPage />
</main>
);
}

4. 차량 정보 인용
더보기
src/data/quotationMock.ts
export const quotationMock = [
// 차량명, 연식, 예상금액
{ carName: "아우디", year: 2020, price: 100000000 },
{ carName: "벤츠", year: 2021, price: 110000000 },
{ carName: "BMW", year: 2022, price: 120000000 },
];
src/components/QuotationCard.tsx
// itcr (import type component return)
type Quotation = {
carName: string;
year: number;
price: number;
};
export default function QuotationCard({ carName, year, price }: Quotation) {
return (
<div className="w-1/4 h-1/4 bg-gray-200 rounded-md shadow-lg p-4 m-8">
<h2>{carName}</h2>
<p>{year}</p>
<p>{price}</p>
</div>
);
}
src/pages/QuotationPage.tsx
// itcr (import, type, component, return)
import QuotationCard from "../components/QuotationCard";
import { quotationMock } from "../data/quotationMock";
export default function QuotationPage() {
return (
<main>
{quotationMock.map((item) => (
<QuotationCard
carName={item.carName}
year={item.year}
price={item.price}
/>
))}
</main>
);
}
src/App.tsx
import GreetingPage from "./pages/GreetingPage";
import ApplyScrapPage from "./pages/ApplyScrapPage";
import QuotationPage from "./pages/QuotationPage";
export default function App() {
return (
<main>
{/* <GreetingPage /> */}
{/* <ApplyScrapPage /> */}
<QuotationPage />
</main>
);
}

5. 스크랩이 끝난 결과
더보기
src/data/completedData.ts
export const completedData = [
{ user: "아무개", car: "현대", date: "2025-07-16" },
{ user: "아무개2", car: "현대2", date: "2025-07-17" },
{ user: "아무개3", car: "현대3", date: "2025-07-18" },
];
src/components/SummaryTable.tsx
type Complete = {
user: string;
car: string;
date: string;
};
export default function SummaryTable({ user, car, date }: Complete) {
return (
<div className="m-8">
<h2>{user}</h2>
<p>{car}</p>
<p>{date}</p>
</div>
);
}
src/pages/ScrapCompletePage.tsx
import SummaryTable from "../components/SummaryTable";
import { completedData } from "../data/completedData";
export default function ScrapCompletePage() {
return (
<div>
{completedData.map((item) => (
<SummaryTable user={item.user} car={item.car} date={item.date} />
))}
</div>
);
}
src/App.tsx
import GreetingPage from "./pages/GreetingPage";
import ApplyScrapPage from "./pages/ApplyScrapPage";
import QuotationPage from "./pages/QuotationPage";
import ScrapCompletePage from "./pages/ScrapCompletePage";
export default function App() {
return (
<main>
{/* <GreetingPage /> */}
{/* <ApplyScrapPage /> */}
{/* <QuotationPage /> */}
<ScrapCompletePage />
</main>
);
}

+ α (useState 추가해서 페이지 기능 추가)
더보기
src/App.tsx
import GreetingPage from "./pages/GreetingPage";
import ApplyScrapPage from "./pages/ApplyScrapPage";
import QuotationPage from "./pages/QuotationPage";
import ScrapCompletePage from "./pages/ScrapCompletePage";
import { useState } from "react";
function App() {
const [stage, setStage] = useState(1);
const [count, setCount] = useState(0);
const prevStage = () => {
setStage(stage - 1);
};
const nextStage = () => {
setStage(stage + 1);
};
const countUp = () => {
setCount(count + 1);
};
return (
<div>
<button className="p-4 m-4 bg-blue-500" onClick={countUp}>
카운트 증가{count}
</button>
<button className="p-4 m-4 bg-blue-500" onClick={prevStage}>
이전
</button>
<span>{stage}</span>
<button className="p-4 m-4 bg-blue-500" onClick={nextStage}>
다음
</button>
{stage === 1 && <GreetingPage />}
{stage === 2 && <ApplyScrapPage />}
{stage === 3 && <QuotationPage />}
{stage === 4 && <ScrapCompletePage />}
</div>
);
}
export default App;

※ 추가로 넣은 페이지 기능은 1~4까지만 출력되며, 범위를 넘어가면 출력되지 않음.
반응형
'Front-End > React' 카테고리의 다른 글
| React #17 (훅, 상태관리 - useRef) (1) | 2025.07.17 |
|---|---|
| React #16 (useState, useEffect 연습문제) (1) | 2025.07.17 |
| React #14 (훅, 상태관리 - useState, useEffect) (0) | 2025.07.15 |
| React #13 (포트폴리오 용 여러가지 만들기-프로필 카드) (1) | 2025.07.15 |
| React #12-2 (CSS - daisyUI: Input & Modal) (1) | 2025.07.14 |