한 컴포넌트 내에서 여러개의 상태를 업데이트해야할 때 어떻게 해야할까?
import { useState } from "react";
import "./ExpenseForm.css";
const ExpenseForm = () => {
//이벤트 타겟 값 항상 string으로 읽으니까 초기값 다 ""으로 하자구
//🔥 상태를 각각 따로따로 만드는 방법
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 onSubmit = (e) => {
e.preventDefault();
console.log("뉴뉴뉴");
};
return (
<form onSubmit={onSubmit}>
<div className="new-expense__controls">
<div className="new-expense__controls">
<label htmlFor="new-expense-name">물품</label>
<input
type="text"
id="new-expense-name"
onChange={titleChangeHandler}
/>
</div>
<div className="new-expense__controls">
<label htmlFor="new-expense-amount">금액</label>
<input
type="number"
min="0.01"
step="0.01"
id="new-expense-amount"
onChange={amountChangeHandler}
/>
</div>
<div className="new-expense__controls">
<label htmlFor="new-expense-date">날짜</label>
<input
type="date"
min="2019-01-01"
max="2023-12-31"
id="new-expense-date"
onChange={dateChangeHandler}
/>
</div>
</div>
<div className="new-expense__actions">
<button type="submit">
추가하기
</button>
</div>
</form>
);
};
export default ExpenseForm;
setUserInput({ enteredTitle: e.target.value });
import { useState } from "react";
import "./ExpenseForm.css";
const ExpenseForm = () => {
//이벤트 타겟 값 항상 string으로 읽으니까 초기값 다 ""으로 하자구
//🔥객체로 묶어 관리하는 방법
const [userInput, setUserInput] = useState({
enteredTitle: "",
enteredAmount: "",
enteredDate: "",
});
const titleChangeHandler = (e) => {
// ❗️BAD
setUserInput({ enteredTitle: e.target.value });
console.log("Title changed!");
};
const amountChangeHandler = (e) => {
// ❗️BAD
setUserInput({ enteredAmount: e.target.value });
console.log("Amount changed!");
};
const dateChangeHandler = (e) => {
// ❗️BAD
setUserInput({ enteredDate: e.target.value });
console.log("Date changed!");
};
//...
setUserInput({ ...userInput, enteredTitle: e.target.value });
기존 값을 복사하기 위해 이전 state의 스냅샷에 의존하여 이전 state 전체를 복사해온 후, 새로운 값을 오버라이드하는 방법이다.
import { useState } from "react";
import "./ExpenseForm.css";
const ExpenseForm = () => {
//이벤트 타겟 값 항상 string으로 읽으니까 초기값 다 ""으로 하자구
//🔥객체로 묶어 관리하는 방법
const [userInput, setUserInput] = useState({
enteredTitle: "",
enteredAmount: "",
enteredDate: "",
});
const titleChangeHandler = (e) => {
// 🥺 Not Bad, But Not Best!
setUserInput({ ...userInput, enteredTitle: e.target.value });
console.log("Title changed!");
};
const amountChangeHandler = (e) => {
// 🥺 Not Bad, But Not Best!
setUserInput({ ...userInput, enteredAmount: e.target.value });
console.log("Amount changed!");
};
const dateChangeHandler = (e) => {
// 🥺 Not Bad, But Not Best!
setUserInput({ ...userInput, enteredDate: e.target.value });
console.log("Date changed!");
};
//...
setUserInput((prevState) => {
return { ...prevState, enteredTitle: e.target.value };
});
setState()함수를 호출하고 그 인자로 함수를 전달한다.
전달된 함수의 인자에는 이전 state값을 스냅샷을 받아 전달하고, 새로운 state의 스냅샷을 반환한다.
이전 상태 값에 따라 상태를 업데이트할 경우 이 함수 구문이 베스트다.
리액트가 상태 업데이트 스케줄(예약)을 가지고 있기 때문에 바로 실행하지는 않는다는 사실을 기억하자!
3번으로 할 경우, 리액트는 이 안에 있는 함수에서 prevState 상태의 스냅샷이 가장 최신 상태의 스냅샷이라는 것과 항상 계획된 상태 업데이트를 염두에 두고 있다는 것을 보장한다.
3번 방법은 항상 최신의 스냅샷으로 작업할 수 있도록 하는 안전한 방법이다. 따라서 이전 상태에 따라 상태를 업데이트를 해야 한다면 3번, 함수 구문을 사용하자!
import { useState } from "react";
import "./ExpenseForm.css";
const ExpenseForm = () => {
//이벤트 타겟 값 항상 string으로 읽으니까 초기값 다 ""으로 하자구
//🔥객체로 묶어 관리하는 방법
const [userInput, setUserInput] = useState({
enteredTitle: "",
enteredAmount: "",
enteredDate: "",
});
const titleChangeHandler = (e) => {
//😇 Good!
setUserInput((prevState) => {
return { ...prevState, enteredTitle: e.target.value };
});
console.log("Title changed!");
};
const amountChangeHandler = (e) => {
// 😇 Good!
setUserInput((prevState) => {
return { ...prevState, enteredAmount: e.target.value };
});
console.log("Amount changed!");
};
const dateChangeHandler = (e) => {
// 😇 Good!
setUserInput((prevState) => {
return { ...prevState, enteredDate: e.target.value };
});
console.log("Date changed!");
};
//...