본문 바로가기

공부기록/[강의노트] Udemy React 완벽가이드 1~100

# 61 [udemy React 완벽 가이드 노트] 자식 컴포넌트의 값을 부모에게 전달하기

ExpenseForm.js파일 

자식 컴포넌트 ExpenseForm에서 만든 expenseData 객체를

부모컴포넌트인 NewExpense.js 파일의 NewExpense 컴포넌트로 전달해주는 방법 

 


 

 

왜 하는가?


App.js파일에서 expenses라는 객체를 관리하고 있는데,

const expenses = [
    {
      id: "e1",
      title: "Toilet Paper",
      amount: 94.12,
      date: new Date(2021, 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),
    },
  ];

이것을 ExpenseForm에서 받아온 값으로 expense 객체에 다음 객체를 동적으로 추가해주기 위해서.

 

  • App.js는 NewExpense컴포넌트를 쓰고 있는  부모컴포넌트
  • NewExpense컴포넌트는 ExpenseForm컴포넌트를 쓰고있는 부모컴포넌트

그러므로 전달은 

ExpenseForm의 data => NewExpense에게 전달 => App에게 전달

하여야 한다.

 

 

ExpenseForm.js 파일의 input의 onChange 특성을 통해 이해하기


<input
	type="text"
	onChange={titleChangeHandler}
 	value={enteredTitle}
 />

title을 변경하기 위해 input의 사용자 입력을 수신하고 있다. 

사용자가 입력하게 되면 titleChangeHandler 함수가 실행되고

우리는 

const titleChangeHandler = e => {
    setEnteredTitle(e.target.value);
  };

 titleChangeHandler 함수에서

디폴트 이벤트 객체를 얻게 된다.

input은 브라우저가 제공하는 내장 컴포넌트라고 할 수 있다. 

DOM의 엘리먼트로 해석될 수 있다. 

그러나 컴포넌트의 특징을 갖는다. 

 

이 onChange속성을 이용해

컴포넌트에 일부 props를 설정할 수 있다. 

리액트는 우리가 onChange속성에 설정한 값을 보고 렌더링된 입력 요소에 있는 리스너를 추가한다. 

 

 

이것을 우리가 생성한 컴포넌트에서도 적용할 수 있다. 

 

자체 이벤트 속성을 생성해서 값으로 함수를 가질 수 있고

부모컴포넌트로부터 자식컴포넌트로  전달할 수 있게 되고 

자식 컴포넌트에서 그 함수를 호출할 수 있다. 

자식 컴포넌트에서 함수를 호출할 때 함수에 매개변수로 데이터를 전달할 수 있게 된다. 

 

 

   

 

 

1단계

 

ExpenseForm.js에서 만든 객체 expenseData를 NewExpense.js로 전달해주기


 

      ▶ NewExpenses.js파일에 새로운 속성 추가하기

import React from "react";
import ExpenseForm from "./ExpenseForm";
import "./NewExpense.css";

const NewExpense = () => {
  const onSaveExpenseDataHandler = enteredExpenseData => {
    const expenseData = {
      ...enteredExpenseData,
      id: Math.random().toString(),
    };
    console.log(expenseData);
  };
  return (
    <div className="new-expense">
      <ExpenseForm onSaveExpenseData={onSaveExpenseDataHandler} />
    </div>
  );
};

export default NewExpense;

onSaveExpenseData라는 속성을 만들어준다.

 

onSaveExpenseData에서 on을 앞에 붙인 이유는 

그 속성에 대한 값은 함수여야 하고 

그 함수는 컴포넌트 내부에서 어떤 일이 벌어졌을 때 (여기선 폼을 서브밋할 때)

작동되는 함수라는 의미를 내포하고 있다. 

네이밍 컨벤션은 마음대로 해도 되지만  on이라는 것을 붙임으로써 그 속성을 드러낼 수 있다. 

 

 

onSaveExpenseData속성에 바인딩된 onSaveExpenseDataHandler 함수를 만들어준다.

const onSaveExpenseDataHandler = enteredExpenseData => {
    const expenseData = {
      ...enteredExpenseData,
      id: Math.random().toString(),
    };
    console.log(expenseData);
  };

 

ExpenseForm에서 생성된 enteredExpenseData 를 expenseData에 카피하고, 

새로운 id키를 랜덤하게 넣어주었다. 

 

 

2단계

 

커스텀 컴포넌트에서 onSaveExpenseData함수 사용하기


input 컴포넌트는 빌트인 컴포넌트로서

input컴포넌트에서 onChange속성에 titleChangeHandler함수를 전달해서 

리액트는 내부에 event리스너를 추가하고

이벤트가 발생할 때마다 자동으로 titleChangeHandler함 수를 부른다. 

 

 

그러나 우리가 만든 커스텀 컴포넌트의 속성에 전달된 함수는

그 커스텀 컴포넌트 안에서 수동으로 실행하여야 한다.

 

const ExpenseForm = props => {

ExpenseForm에 props를 받아서 NewExpense파일에서 보내준 onSaveExpenseData속성을 받아온다.

 

 

ExpenseForm.js파일 중 submitHandler 함수


const submitHandler = e => {
    e.preventDefault();
    const expenseData = {
      title: enteredTitle,
      amount: enteredAmount,
      date: new Date(enteredDate),
    };

    props.onSaveExpenseData(expenseData);
    setEnteredAmount("");
    setEnteredTitle("");
    setEnteredDate("");
    console.log(expenseData);
  };

onSaveExpenseData가 함수이기때문에 실행할 수 있다. 

이제 다른 컴포넌트인 ExpenseForm 컴포넌트에서 onSaveExpenseDataHandler를 실행할 수 있게 되었다. 

 

 

 

정리해보기


NewExpense컴포넌트에서 saveExpenseDataHandler함수를 호출하고

매개변수로 데이터를 전달할 수 있다. 

 

const NewExpense = () => {
  const onSaveExpenseDataHandler = enteredExpenseData => {
    const expenseData = {
      ...enteredExpenseData,
      id: Math.random().toString(),
    };
    console.log(expenseData);
  };

 

ExpenseForm 컴포넌트에서 onSaveExpenseData를 호출할 때 생성한 expenseData를 

인자로 전달한다. 

 

const submitHandler = e => {
    e.preventDefault();
    const expenseData = {
      title: enteredTitle,
      amount: enteredAmount,
      date: new Date(enteredDate),
    };

    props.onSaveExpenseData(expenseData);

그것이 NewExpense컴포넌트에서 매개변수로 받는

enteredExpenseData이다.