둘 다 데이터를 담는 컨테이너의 역할을 담당.
props는 모듈 간 데이터를 전달하는데 이용, state는 한 모듈안에서 데이터를 쓰는데 이용.
state는 꼭 필요한 게 아니며, 가능하면 지양해야 프로그램이 깔끔해지는 특성을 지니고 있음.
부모에서 자식 component 간 props를 통해 데이터를 아래로 전달해주는 것을 확인할 수 있었음.
그러면 반대로 자식에서 부모 componenet로는 어떻게 데이터를 전달할 수 있을까?
함수를 인자로 전달하여, 해당 함수에 업데이트 된 data(state)를 넣어서 돌려주면 lift-up 해 줄 수 있다.
다음 두 script는 부모-자식 관계이며, Form이 자식 component임.
import React from 'react';
import './NewExpense.css'
import ExpenseForm from './ExpenseForm'
// ExpenseForm에서 작성된 expense data를 이곳으로 보내보자.
const NewExpense = (props) => {
const saveExpenseDataHandler = (enteredExpenseData) => {
const expenseData = {
...enteredExpenseData,
id: Math.random().toString() // submitHandler로 입력된 데이터를 가져오고, id 추가해준다.
};
props.onAddExpense(expenseData); // App.js에서 넘겨준 함수인자 onAddExpense에 위의 데이터 컨테이너인 expenseData를 넣고
// 실행시키면 app.js와 연결된다.
console.log('In NewExpense', expenseData)
};
return (
<div className = "new-expense">
<ExpenseForm onSaveExpenseData = {saveExpenseDataHandler} />
</div>
)
};
// <ExpenseForm onSaveExpenseData = {saveExpenseDataHandler} /> => pointer edit,
// lifting state를 가능케하는 핵심코드. onSaveExpenseData 함수를 만들어 데이터를 끌어오는 ExpenseForm 컴포넌트에 전달해주자.
// App.js에 props로 받은 addExpenseHandler를 15번째 줄에서 실행 및 인자로 expenseData를 app으로 넘겨준다.
export default NewExpense;
import React, {useState} from 'react';
import './ExpenseForm.css'
const ExpenseForm = (props) => {
// 하기 세 state 독립적으로 작동한다.
// *** useState를 쓰면 state를 업데이트 시켜주는 setUserInput을 실행시키고 그 결과를 userInput에 할당. ***
const [enteredTitle, setEnteredTitle] = useState('');
const [enteredAmount, setEnteredAmount] = useState('');
const [enteredDate, setEnteredDate] = useState('');
const titleChangeHandler = event => {
setEnteredTitle(event.target.value);
// setUserInput ({
// ...userInput,
// enteredTitle: event.target.value // 덮어써서, 나머지 두 개의 state가 변하지 않게하기.
// }) //이벤트 객체 내에 있는 타이핑 된 내용을 타겟팅하여 로깅한다. // value 안에는 항상 string 처리가 되어 있다.
// setUserInput((prevState) => {
// return {...prevState,enteredTitle: event.target.value};
// });
// 전의 state를 바탕으로 update 시키고 싶을 경우, 상기 form을 쓸 것.
};
const amountChangeHandler = event => {
setEnteredAmount(event.target.value);
};
const dateChangeHandler = event => {
setEnteredDate(event.target.value);
};
const submitHandler = (event) => {
event.preventDefault(); // 화면 깜박임을 방지.
const expenseData = { // 위에서 생성된 state를 여기다 저장하자.
title: enteredTitle,
amount: enteredAmount,
date: new Date(enteredDate)
};
console.log(expenseData)
props.onSaveExpenseData(expenseData); // 1. NewExpense에서 전달받은 saveExpenseDateHandler를 불러옴.
// 2. 입력된 data를 expenseData에 만든 후, props에 저장해주자. lifting-up.
setEnteredAmount('') // 초기화
setEnteredDate('')
setEnteredTitle('')
};
// onSubmit: submit 후 이벤트 실행.
// onChange: 한 텍스트 쓸때마다 반응. 단, input 창에는 데이터가 출력되지 않는다.
return (
<form onSubmit= {submitHandler}>
<div className="new-expense__controls">
<div className="new-expense__control">
<label> Title </label>
<input type='text' value = {enteredTitle} onChange={titleChangeHandler}/>
</div>
<div className="new-expense__control">
<label> Amount </label>
<input type='number' value = {enteredAmount} min="0.01" step="0.01" onChange={amountChangeHandler}/>
</div>
<div className="new-expense__control">
<label> Date </label>
<input type='date' value = {enteredDate} min="2019-01-01" max="2022-12-31" onChange={dateChangeHandler}/>
</div>
</div>
<div className ="new-expense__actions">
<button type ='submit' > Add expense </button>
</div>
</form>
)
};
export default ExpenseForm;
props.onSaveExpenseData(expenseData);
props.onAddExpense(expenseData);
이해하기까지 너무 많은 시간이 걸렸다. 언제쯤 react를 정복할 수 있을까...