[React] 상향식 통신: 데이터 부모 컴포넌트로 전달하기

summereuna🐥·2023년 3월 11일
0

React JS

목록 보기
29/69

React의 상향식 통신

예제

📍 현재 컴포넌트 구조
App(비용 data 배열) > NewExpense > ExpenseForm(새로운 비용 data 생성)

📍 App.js

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;

📍 NewExpense.js

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;

📍 ExpenseForm.js

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는 오직 부모에서 자식으로 직접 전달만 가능, 중간 단계 생략 못함)
  • 자식 컴포넌트가 부모 컴포넌트로 데이터를 넘겨줄 때: 이벤트 핸들러 사용하는 것과 비슷하다.
    1. 부모 컴포넌트에서 인자를 전달하는 포인터 함수를 만들고, props로 그 함수를 자식 컴포넌트에게 전달
    2. 자식컴포넌트에서 그 함수를 호출하여 인자에 새로운 데이터 전달
      그러면 함수는 매개변수로 새로운 데이터를 전달 받을 수 있음

📚(관례) props의 이름을 on~ 으로 짓는 이유

<ExpenseForm onSaveExpenseData={saveExpenseDataHandler}/>

인자를 전달하는 포인터 함수를 지칭할 때 props의 이름을 on~ 이라고 짓는다.

  • 컴포넌트 내부에서 어떤 일이 벌어졌을 때 트리거(작동)되는 함수를 담고있다는 의미를 담기 위함이다.
  • 위 예제의 경우, onSaveExpenseData라는 이름의 prop을 통해 인자를 전달하는 포인터 함수인 saveExpenseDataHandler를 ExpenseForm 컴포넌트에 전달하고 있다.
    • 이 뜻은 사용자가 enteredExpenseData를 저장할 때, 즉 폼이 제출될 때 트리거(작동)하겠다는 의미를 포함하고 있다.
    • 즉, onSaveExpenseData prop에 대한 값인 saveExpenseDataHandler함수는 ExpenseForm 컴포넌트 내부에서 호출될 수 있는 함수라는 것을 의미한다.

📝 요약

리액트의 상향식 통신

  1. 상위 컴포넌트에서 데이터를 저장하는 함수를 만들어 하위 컴포넌트에 props으로 포인터를 전달한다.
  2. 하위 컴포넌트에서 props으로 전달된 함수를 호출하고 인자로 입력된 데이터 값을 보낸다.
  3. 그러면 그 함수는 입력된 데이터 값을 매개변수로 받아 실행된다.
profile
Always have hope🍀 & constant passion🔥

0개의 댓글