📍 현재 컴포넌트 구조
App(비용 data 배열) > NewExpense > ExpenseForm(새로운 비용 data 생성)
import Expenses from "./components/Expenses/Expenses";
import NewExpense from "./components/NewExpense/NewExpense";
const App = () => {
//여러개의 비용 아이템이 들어있는 배열
const expenses = [
{
id: "e1",
title: "Toilet Paper",
amount: 94.12,
date: new Date(2020, 7, 14),
},
{ id: "e2", title: "New TV", amount: 799.49, date: new Date(2021, 2, 12) },
{
id: "e3",
title: "Car Insurance",
amount: 294.67,
date: new Date(2021, 2, 28),
},
{
id: "e4",
title: "New Desk (Wooden)",
amount: 450,
date: new Date(2021, 5, 12),
},
];
//🔥 1-1. expense 배열에 data 객체 추가할 함수를 만든다.
const addExpenseHandler = (newExpense) => {
console.log("@ App.js");
console.log(newExpense);
};
return (
<div>
//🔥 1-2. 자식 컴포넌트인 NewExpense에 props으로 addExpenseHandler함수를 보낸다.
<NewExpense onAddExpenseData={addExpenseHandler} />
<Expenses items={expenses} />
</div>
);
};
export default App;
import "./NewExpense.css";
import ExpenseForm from "./ExpenseForm";
//🔥 1-3. props으로 onAddExpenseData에 넣어진 함수를 받는다.
const NewExpense = (props) => {
//🌈 2-1. 데이터를 저장할 함수를 만든다.
const saveExpenseDataHandler = (enteredExpenseData) => {
//🌈 2-2. ExpenseForm에서 입력된 data를 매개변수로 받아 복사한다.
const expenseData = {
...enteredExpenseData,
id: Math.random().toString(),
};
//🔥 1-4. 상위 컴포넌트인 App.js에서 props으로 받은 함수에 저장할 data를 인자로 전달한다.
props.onAddExpenseData(expenseData);
};
return (
<div className="new-expense">
//🌈 2-3. 자식 컴포넌트인 ExpenseForm에 props으로 saveExpenseDataHandler함수를 보낸다.
<ExpenseForm onSaveExpenseData={saveExpenseDataHandler} />
</div>
);
};
export default NewExpense;
import { useState } from "react";
import "./ExpenseForm.css";
// 🌈 2-4. props으로 함수를 받아 온다.
const ExpenseForm = (props) => {
const [enteredTitle, setEnteredTitle] = useState("");
const [enteredAmount, setEnteredAmount] = useState("");
const [enteredDate, setEnteredDate] = useState("");
const titleChangeHandler = (e) => {
setEnteredTitle(e.target.value);
};
const amountChangeHandler = (e) => {
setEnteredAmount(e.target.value);
};
const dateChangeHandler = (e) => {
setEnteredDate(e.target.value);
};
const submitHandler = (e) => {
e.preventDefault();
const expenseData = {
title: enteredTitle,
amount: enteredAmount,
date: new Date(enteredDate),
};
// 🌈 2-5. props로 전달받은 onSaveExpenseData함수에 데이터를 인자로 전달한다. 그러면 부모 컴포넌트로 입력받은 데이터가 전달된다.
props.onSaveExpenseData(expenseData);
setEnteredTitle("");
setEnteredAmount("");
setEnteredDate("");
};
return (...);
ExpenseForm
컴포넌트에서 새롭게 생성한 비용 data를 expense 배열이 있는 App
컴포넌트에 전달해야 한다.
props
활용📚(관례) props의 이름을 on~ 으로 짓는 이유
<ExpenseForm onSaveExpenseData={saveExpenseDataHandler}/>
인자를 전달하는 포인터 함수를 지칭할 때 props의 이름을 on~ 이라고 짓는다.
- 컴포넌트 내부에서 어떤 일이 벌어졌을 때 트리거(작동)되는 함수를 담고있다는 의미를 담기 위함이다.
- 위 예제의 경우, onSaveExpenseData라는 이름의 prop을 통해 인자를 전달하는 포인터 함수인
saveExpenseDataHandler
를 ExpenseForm 컴포넌트에 전달하고 있다.
- 이 뜻은 사용자가 enteredExpenseData를 저장할 때, 즉 폼이 제출될 때 트리거(작동)하겠다는 의미를 포함하고 있다.
- 즉, onSaveExpenseData prop에 대한 값인
saveExpenseDataHandler
함수는 ExpenseForm 컴포넌트 내부에서 호출될 수 있는 함수라는 것을 의미한다.