import { useState } from "react";
import "./ExpenseForm.css";
const ExpenseForm = () => {
const [enteredTitle, setEnteredTitle] = useState("");
const [enteredAmount, setEnteredAmount] = useState("");
const [enteredDate, setEnteredDate] = useState("");
const titleChangeHandler = (e) => {
setEnteredTitle(e.target.value);
console.log("Title changed!");
};
const amountChangeHandler = (e) => {
setEnteredAmount(e.target.value);
console.log("Amount changed!");
};
const dateChangeHandler = (e) => {
setEnteredDate(e.target.value);
console.log("Date changed!");
};
const submitHandler = (e) => {
//1. 페이지 리로드 방지
e.preventDefault();
//2. state 결합하기: 제출된 폼의 내용을 모두 담은 객체 생성
const expenseData = {
title: enteredTitle,
amount: enteredAmount,
//날짜 생성자로 날짜 생성 후, 해당 날짜 문자열 분석하여 날짜 객체로 변환한 enteredDate 전달
date: new Date(enteredDate),
};
//3. 양방형 바인딩: 입력 후 form에 적은 값 화면에서 없애기
setEnteredTitle("");
setEnteredAmount("");
setEnteredDate("");
};
return (
<form onSubmit={submitHandler}>
<div className="new-expense__controls">
<div className="new-expense__controls">
<label htmlFor="new-expense-name">물품</label>
<input
type="text"
onChange={titleChangeHandler}
value={enteredTitle}
/>
</div>
<div className="new-expense__controls">
<label htmlFor="new-expense-amount">금액</label>
<input
type="number"
min="0.01"
step="0.01"
onChange={amountChangeHandler}
value={enteredAmount}
/>
</div>
<div className="new-expense__controls">
<label htmlFor="new-expense-date">날짜</label>
<input
type="date"
min="2019-01-01"
max="2023-12-31"
onChange={dateChangeHandler}
value={enteredDate}
/>
</div>
</div>
<div className="new-expense__actions">
<button type="submit">추가하기</button>
</div>
</form>
);
};
export default ExpenseForm;
브라우저는 form이 제출될 때 마다 웹페이지를 호스팅하고 있는 서버에 요청을 보내기 때문에 페이지를 리로드한다. JS로 수동으로 데이터를 수집하여 결합하는 방법으로 폼을 제출하고 싶다면 이러한 기본 동작을 비활성화 하면 된다.
event.preventDefault();
로 기본요청이 보내지는 것을 막을 수 있다.
서버로 어떤 요청도 보내지 않기 때문에 페이지가 리로드되지 않는다. 계속해서 JS로 핸들링할 수 있다.
현재 state를 각각 생성했기 때문에 하나의 오브젝트로 담아야 한다.
form으로 받은 entered states를 아래의 코드 처럼 객체에 담아주면 된다.
const expenseData = {
title: enteredTitle,
amount: enteredAmount,
date: new Date(enteredDate),
};
바닐라 JS에서는 엘리먼트를 하나씩 가져와서 value의 내용을 지워주는 방식으로 진행했었다. 리액트에서는 state의 양방향 바인딩을 활용하여 그 기능을 구현할 수 있다.
<input
type="text"
onChange={titleChangeHandler}
value={enteredTitle}
/>
setState("");
로 각각의 state를 빈문자열로 재설정한다.const submitHandler = (e) => {
e.preventDefault();
const expenseData = {
title: enteredTitle,
amount: enteredAmount,
date: new Date(enteredDate),
};
setEnteredTitle("");
setEnteredAmount("");
setEnteredDate("");
};