[practice] props - useState, function

이아현·2025년 2월 13일
0

TypeScript

목록 보기
6/6
// 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>
  );
}
profile
PM을 지향하는 FE 개발자 이아현입니다 :)

0개의 댓글