// App.tsx
import { useState } from "react";
import Header from "./components/Header.tsx";
import reactImg from "./assets/react.svg";
import CourseGoalList from "./components/CourseGoalList.tsx";
// 목표(CourseGoal) 타입 정의
type CourseGoal = {
title: string;
description: string;
id: number;
};
export default function App() {
// 목표 리스트 상태 관리
const [goals, setGoals] = useState<CourseGoal[]>([]);
// 새로운 목표 추가 함수
function handleAddGoal() {
setGoals((prevGoals) => {
const newGoal: CourseGoal = {
id: Math.random(), // 랜덤한 ID 생성
title: "Learn React + TS", // 기본 제목
description: "Learn it in depth", // 기본 설명
};
return [...prevGoals, newGoal]; // 기존 목표 리스트에 새로운 목표 추가
});
}
// 목표 삭제 함수
function handleDeleteGoal(id: number) {
setGoals((prevGoals) => prevGoals.filter((goal) => goal.id !== id));
}
return (
<main>
{/* 헤더 컴포넌트, 제목과 이미지 전달 */}
<Header image={{ src: reactImg, alt: "A list of goals" }}>
<h1>Your goal list</h1>
</Header>
{/* 목표 추가 버튼 */}
<button onClick={handleAddGoal}>Add Goal</button>
{/* 목표 리스트 컴포넌트 */}
<CourseGoalList goals={goals} onDeleteGoal={handleDeleteGoal} />
</main>
);
}
// Header.tsx
import { ReactNode } from "react";
// Header 컴포넌트의 props 타입 정의
type HeaderProps = {
children: ReactNode;
image: {
src: string;
alt: string;
};
};
export default function Header({ image, children }: HeaderProps) {
return (
<header>
<img src={image.src} alt={image.alt} />
{children}
</header>
);
}
// CourseGoalList.tsx
import CourseGoal from "./CourseGoal";
import { CourseGoal as CGoal } from "../App.tsx";
// CourseGoalList 컴포넌트의 props 타입 정의
type CourseGoalListProps = {
goals: CGoal[];
onDeleteGoal: (id: number) => void;
};
export default function CourseGoalList({
goals,
onDeleteGoal,
}: CourseGoalListProps) {
return (
<ul>
{goals.map((goal) => (
<li key={goal.id}>
{/* 개별 목표를 렌더링하는 CourseGoal 컴포넌트 */}
<CourseGoal id={goal.id} title={goal.title} onDelete={onDeleteGoal}>
<p>{goal.description}</p>
</CourseGoal>
</li>
))}
</ul>
);
}
// CourseGoal.tsx
import { PropsWithChildren } from "react";
// CourseGoal 컴포넌트의 props 타입 정의
type CourseGoalProps = PropsWithChildren<{
id: number;
title: string;
onDelete: (id: number) => void;
}>;
export default function CourseGoal({
title,
id,
children,
onDelete,
}: CourseGoalProps) {
return (
<article>
<div>
<h2>TITLE : {title}</h2>
{children}
</div>
{/* 삭제 버튼 클릭 시 onDelete 함수 실행 */}
<button onClick={() => onDelete(id)}>Delete</button>
</article>
);
}