title, calorie, content 3가지 입력 input을 받아서 상태관리를 하려면 3가지 useState를 만들고 상태를 관리하게 된다.
function FoodForm() {
const [title, setTitle] = useState('');
const [calorie, setCalorie] = useState(0);
const [content, setContent] = useState('');
return (
<form>
<input name="title" value={title} onChange={(e)=>{setTitle(e.target.value)}}></input>
<input type="number" name="calorie" value={calorie} onChange={(e)=>{setCalorie(e.target.value)}}></input>
<input name="content" value={content} onChange={(e)=>{setcontent(e.target.value)}}></input>
</form>
);
}
3가지 속성에 대해 한 번에 제출되는 이벤트를 만들고 싶을 때,
이벤트 객체의 event.target.value
와 event.target.name
속성을 이용하면 3가지 상태를 1의 객체로 상태 관리를 할 수 있다.
function FoodForm() {
// 3가지 속성을 1개의 객체로 만든다.
const [values, setValues] = useState({
title: "",
calorie: 0,
content: "",
});
const handleChange = (e) => {
const { name, value } = e.target;
// [name] 으로 key 값을 정하면 name 변수가 변하는 값에 따라 key를 다르게 지정할 수 있다.
setValues((preValues)=> {return { ...preValues, [name]: value }});
/* 만약 비동기로 데이터를 받아온다면,
데이터를 받아오는 동안 시점 차이로 인해 잘못된 이전 값을 참조할 수 있으므로 콜백함수로 처리 */
const handleSubmit = (e) => {
e.preventDefault(); // submit의 기본 동작인 페이지 이동을 막음
console.log(values);
};
return (
<form className="ReviewForm" onSubmit={handleSubmit}>
<input name="title" value={values.title} onChange={handleChange} />
<input name="calorie" value={values.calorie} type="number" onChange={handleChange} />
<input name="content" value={values.content} onChange={handleChange} />
<button onSubmit={handleSubmit}> 확인 </button>
</form>
);
}
<input>
태그에 지정해 준 name 속성에 따라 event.target.name 이 바뀌므로 객체의 key를 [ name ]
으로 정해서 각 입력 폼마다 다른 key 값을 갖게 할 수 있다.
setValues({...values, [name]: value })
로 하게되면, 데이터를 비동기로 받아올 때, 참조하는 시점에 따라 values 값이 바뀔 수 있다.
따라서 정확한 직전 values 값을 받아오기 위해서는 콜백함수를 사용해야한다. 콜백함수가 불려진 시점의 values를 참조해 values 값을 세팅하게 된다.
{return { ...preValues, [name]: value }});
숫자를 입력받는 input에 대해 type에 따라 값이 숫자가 될 수 있도록 <input >
추가해줄 수도 있다.
function FoodForm() {
// 내용 생략
// e.target.type을 받아 e.target.value를 리턴하는 함수
const getNumber = (type, value)=>{
switch(type){
case "number" :
return Number(value) || 0;
default:
return value;
}
}
const handleChange = (e) => {
const { name, value, type } = e.target;
setValues((preValues)=> {return { ...preValues, [name]: getNumber(type, value) }});
return (
// ... 생략
// type = "number"
<input name="calorie" value={values.calorie} type="number" onChange={handleChange} />
// ... 생략
);
}