[코드잇] 리액트 - 하나의 state로 여러 입력 from 구성하기

iberis2·2023년 4월 10일
0

React 리액트

목록 보기
15/20

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.valueevent.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} />
      // ... 생략
    );
  
}
profile
React, Next.js, TypeScript 로 개발 중인 프론트엔드 개발자

0개의 댓글