input의 개수가 여러 개가 됐을 때는, 단순히 useState를 여러 번 사용하고 onChange도 여러 개 만들어서 구현할 수 있지만, 가장 좋은 방법은 아닙니다.
더 좋은 방법은 input에 name을 설정하고 이벤트가 발생했을 때 이 값을 참조하는 것입니다.
그리고 useState에서는 문자열이 아니라 객체 형태의 상태를 관리해주어야 합니다.
function InputSample() {
const [inputs, setInputs] =useState({name:'', nickname:''});
const {name, nickname} = inputs; // 비구조화 할당을 통해 값 추출
const onChange = (e) => {
const {value,name} = e.target; // 우선 e.target에서 name과 value 추출
setInputs({...inputs, //기존의 input 객체 복사한 뒤
[name]: value // name 키를 가진 값을 value로 설정
});
}
const onReset = () => {setInputs({name:'', nickname:''})};
return (
<div>
<input name='name' placeholder='이름' onChange={onChange} value={name} />
<input name='nickname' placeholder='닉네임' onChange={onChange} value={nickname}/>
<button onClick={onReset}>초기화</button>
<div>
<b>값: </b>
{name} ({nickname})
</div>
</div>
);
}
export default InputSample;
리액트 상태에서 객체를 수정해야 할 때는 ...(스프레드 문법) 으로,
객체를 모두 펼쳐서 기존 객체를 복사해서 새 객체를 만든 후, 새 값으로 덮어씌운다.
= 불변성을 지킨다
불변성을 지켜주어야 리액트 컴포넌트에서 상태가 업데이트 됐음을 감지할 수 있고
이에 따라 필요한 리렌더링이 진행된다.
불변성을 지켜주어야만 컴포넌트 성능 최적화를 제대로 할 수 있다.
setState는 shouldComponentUpdate(nextProps, nextState)를 트리거하는데 이 메소드의 boolean 반환값에 따라 render호출 여부가 결정된다.
이 메소드를 재정의하지 않으면 setState 호출 시마다 render가 호출된다.
본문의 '최적화'는 shouldComponentUpdate 재정의를 통해 render 호출 여부를 결정하는 것을 말한다.