๐ŸŒŸํ˜„์žฌ ํ•™์Šต ์ค‘์ธ react - components ๊ตฌ์กฐ

  1. ํ•˜ํ–ฅ์‹ ์ „๋‹ฌ - props๋กœ ๋ฐ์ดํ„ฐ ์ „๋‹ฌํ•˜๋Š” ๋ฐฉ๋ฒ• !

  2. ์ƒํ–ฅ์‹ ์ „๋‹ฌ - ์ง€๊ธˆ ExpenseForm์—์„œ ์ถ”๊ฐ€ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ App.js์— ์˜ฌ๋ ค์„œ ๋ถ™์—ฌ์•ผ ํ•˜๋Š” ์ƒํ™ฉ

    Untitled

Untitled

โญ์ƒํ–ฅ์‹ ์ „๋‹ฌ props ์ฝ”๋“œ ๋ฆฌ๋ทฐ

import React, { useState } from 'react';
import './ExpenseForm.css';

const ExpenseForm = ({ onAdd, onCancel }) => {

  // ์ž…๋ ฅ์นธ์— ์žˆ๋Š” 3๊ฐœ์˜ ๊ฐ’์„ ๊ฐ๊ฐ์˜ ์ƒํƒœ๊ฐ’์œผ๋กœ ๊ด€๋ฆฌ - ๋‹จ์ผ๊ฐ’ ์ƒํƒœ
  // const [title, setTitle] = useState('');
  // const [price, setPrice] = useState(0);
  // const [date, setDate] = useState(null);

  // โ•โ• ์ž…๋ ฅ์นธ์— ์žˆ๋Š” 3๊ฐœ์˜ ๊ฐ’์„ ํ•˜๋‚˜์˜ ์ƒํƒœ๊ฐ’์œผ๋กœ ๊ด€๋ฆฌ - ๊ฐ์ฒด ์ƒํƒœ
  // ์ดˆ๊ธฐ๊ฐ’์— ์—…๋ฐ์ดํŠธํ•  ์ƒํƒœ๋ฅผ ๊ฐ์ฒดํ˜•ํƒœ๋กœ ๋„ฃ์–ด์ค€๋‹ค !
  const [userInput, setUserInput] = useState({
    title: '',
    price: '',
    date: ''
  });

  // ์˜ค๋Š˜ ๋‚ ์งœ๋ฅผ YYYY-MM-DD ํ˜•์‹์œผ๋กœ ๊ฐ€์ ธ์˜ค๋Š” ํ•จ์ˆ˜
  const getTodayDate = () => {
    const today = new Date();
    const year = today.getFullYear();
    const month = String(today.getMonth() + 1).padStart(2, '0'); // ์›”์€ 0๋ถ€ํ„ฐ ์‹œ์ž‘ํ•˜๋ฏ€๋กœ 1์„ ๋”ํ•ด์คŒ
    const day = String(today.getDate()).padStart(2, '0');
    return `${year}-${month}-${day}`;
  }

  // 1. ์ œ๋ชฉ์ด ์ž…๋ ฅ๋˜์—ˆ์„ ๋•Œ ๋ฐœ์ƒํ•˜๋Š” ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ
  const titleChangeHandler = e => {
    // userInput.title = e.target.value; (X)

    // ๐Ÿ’ฅ๐Ÿ’ฅ ๊ฐ์ฒด๋‚˜ ๋ฐฐ์—ด์ƒํƒœ๋กœ ๊ด€๋ฆฌ๋˜๋Š” useState ์ƒํƒœ๊ฐ’์€ 
    // ์ƒํƒœ๋ณ€๊ฒฝ์‹œ ์ƒˆ๋กœ์šด ๊ฐ์ฒด๋‚˜ ๋ฐฐ์—ด์„ setter์— ์ „๋‹ฌํ•ด์•ผ ํ•จ
    // โœ” ๋น„๋™๊ธฐ๊ฐ€ ์ˆœ์„œ๊ฐ€ ๋ณด์žฅ๋˜์–ด ์žˆ์ง€ ์•Š์•„ ์—…๋ฐ์ดํŠธ๋˜๊ธฐ ์ „ ๊ฐ’์„ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์—
    // prevUserInput์— ์—…๋ฐ์ดํŠธ๋œ ์ตœ์‹  ์ƒํƒœ๋ฅผ ๊ฐ€์ ธ์™€์„œ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค !
    setUserInput(prevUserInput => ({
      ...prevUserInput,
      title: e.target.value
    }));
  };

  // 2. ๊ฐ€๊ฒฉ์ด ์ž…๋ ฅ๋˜์—ˆ์„ ๋•Œ ๋ฐœ์ƒํ•˜๋Š” ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ
  const priceChangeHandler = e => {
    setUserInput({
      ...userInput,
      price: +e.target.value
    });
  };

  // 3. ๋‚ ์งœ๊ฐ€ ์ž…๋ ฅ๋˜์—ˆ์„ ๋•Œ ๋ฐœ์ƒํ•˜๋Š” ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ
  const dateChangeHandler = e => {
    setUserInput({
      ...userInput,
      date: e.target.value
    });
  };

  // ํผ ์ „์†ก ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ
  const submitHandler = e => {
    e.preventDefault(); // ํผ ์ „์†ก ๋ฐฉ์ง€
    // console.log('ํผ์ด ์ „์†ก๋จ!');

    // ์ง€์ถœ ๋‚ด์—ญ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑ - ๊ฐ์ฒด์ƒํƒœ๋กœ ๊ด€๋ฆฌ์‹œ ํ•„์š” ์—†์Œ !
    // const newExpense = {
    //   title,
    //   price,
    //   date
    // };

    console.log(userInput);

    **// App.js์—๊ฒŒ ๋ฐ›์€ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœ - ํ•˜ํ–ฅ์‹์œผ๋กœ ๋ฐ์ดํ„ฐ ๋‹ด์„ ๋ฐ”๊ตฌ๋‹ˆ ๋‚ด๋ ค๋ณด๋‚ธ ๊ฒƒ !
    //โ•โ• - ๋‚ด๋ ค๋ณด๋‚ธ onAdd() ๋ฐ”๊ตฌ๋‹ˆ์— userInput ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ด๋Š”๋‹ค ! -> ํ•ด๋‹น ๋ฐ์ดํ„ฐ๊ฐ€ ํ•„์š”ํ•œ ์ƒํ–ฅ App.js์— userInput ๋ฐ์ดํ„ฐ ๋ณด๋‚ด์ฃผ๊ธฐ !
    onAdd({
      ...userInput,
      date: new Date(userInput.date)
    });**

    // form input ๋น„์šฐ๊ธฐ - ๋“ฑ๋ก ํ›„ ๋นˆ๋ฌธ์ž์—ด๋กœ ์ž…๋ ฅ์ฐฝ์— ๊ฐ’ ๋น„์›Œ์ฃผ๊ธฐ
    setUserInput({
      title: '',
      price: '',
      date: ''
    });

  };

  return (
    <form onSubmit={submitHandler}>
      <div className="new-expense__controls">
        <div className="new-expense__control">
          <label>Title</label>
          <input 
            type="text" 
            onChange={titleChangeHandler} 
            value={userInput.title}
          />
        </div>
        <div className="new-expense__control">
          <label>Price</label>
          <input
            type="number"
            min="100"
            step="100"
            onChange={priceChangeHandler}
            value={userInput.price}
          />
        </div>
        <div className="new-expense__control">
          <label>Date</label>
          <input
            type="date"
            min="2019-01-01"
            max={getTodayDate()}
            onChange={dateChangeHandler}
            value={userInput.date}
          />
        </div>
      </div>
      <div className="new-expense__actions">
        <button type="button" onClick={onCancel}>Cancel</button>
        <button type="submit">Add Expense</button>
      </div>
    </form>
  );
};

export default ExpenseForm;
import "./App.css";
import React from "react";
import ExpenseList from "./components/Expenses/ExpenseList";
import Greet from "./components/Greet";
import Counter from "./components/practice/Counter";
import NewExpense from "./components/new-expense/NewExpense";
import CheckBoxStyle from "./components/practice/CheckBoxStyle";

const App = () => {
  // ์„œ๋ฒ„์—์„œ ์ง€์ถœํ•ญ๋ชฉ JSON ๋ฐฐ์—ด์„ ์‘๋‹ต ๋ฐ›์Œ
  const **expenses** = [
    {
      title: "์ˆ˜์˜์žฅ ๋“ฑ๋ก",
      price: 100000,
      date: new Date(2024, 6 - 1, 3),
    },
    { title: "๋‹ค์ด์†Œ", price: 8000, date: new Date(2024, 7 - 1, 14) },
    {
      title: "๊น€๋ฐฅ",
      price: 4900,
      date: new Date(2024, 7 - 1, 25),
    },
  ];

  **// โ•โ• ExpenseForm์—๊ฒŒ ๋‚ด๋ ค๋ณด๋‚ผ ํ•จ์ˆ˜ -> ๋‚ด๋ ค๋ณด๋‚ธ ๋ฐ”๊ตฌ๋‹ˆ์—์„œ userInput ๋ฐ์ดํ„ฐ ๋‹ด์•„์˜ด !
  const onAddExpense = (userInput) => {
    console.log('App.js๊ฐ€ ๋‚ด๋ ค๋ณด๋‚ธ ํ•จ์ˆ˜ ํ˜ธ์ถœ');
    console.log(userInput);
    // ์œ„์— expenses ๊ฐ์ฒด์— ์ถ”๊ฐ€ํ•˜๊ธฐ ! push   
    expenses.push(userInput);
  }**

  return (
    <>
     <CheckBoxStyle />
     **<NewExpense onSave={onAddExpense}/>**
     <ExpenseList expenses={expenses} />
    </>
  );
};

export default App;