onChange : 변할때마다 실행, 주로 input태그의 이벤트값을 받아와서 name과 value를 비구조화 할당을 통해 추출
비구조화 할당 : 객체를 추출하는 방법
구조분해 할당 : 객체나 배열을 변수로 ‘분해’할 수 있게 해주는 특별한 문법
input에 name을 설정하고 이벤트가 발생했을 때 이 값을 참조
useState에서는 문자열이 아니라 객체 형태의 상태를 관리
리액트에서 객체를 업데이트하게 될때는 기존 객체를 직접 수정하면안되고, 기존 객체를 복사한다음 ( … (spread문법) ), 새로운 객체를 만들어서 새 객체에 변화를 주어야함
why? 리액트 컴포넌트가 re-rendering을 할 때, virtual DOM에서 이전 컴포넌트와 새로 바뀌는 컴포넌트를 비교하게 될텐데 기존 객체를 직접 수정하게 되면 새로 바뀐 컴포넌트에서는 이전 컴포넌트와 같은 상태를 가질 수 있다고 보아 ‘새 객체’에 변화를 주어야한다.
‘리액트에서 불변성을 지켜라’
InputSample.js
import React,{ useState } from 'react';
function InputSample() {
const [inputs, setInputs] = useState({
name : '',
nickname : ''
});
const {name,nickname} = inputs; //비구조화 할당을 통해 값 추출
const onChange = (e) => {
const {name, value} = e.target; //우선 e.target에서 value,name 추출
setInputs ({
...inputs, //기존의 input 객체를 복사한 뒤
[name] : value, // name 키를 가진 값을 value로 설정
});
//setInput자리에서는 [name]값은 name OR nickname
//name을 바꾸거나 nickname을 바꾸겠다. 그래서 이렇게 새로운 객체를 설정해주는 것
}
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;
[name]
은 input
태그의 name
속성의 값.
input
태그에 변경이 생기면 onChange
함수가 호출되고 그 input
태그의 name
속성의 값이 [name]
으로 가는 것
코드에서는 지금 name
속성의 값이 name
, nickname
인 input
태그가 두개 있다.
첫번째 input
에 변경이 발생하면 [name]
에 name
이 들어갈 것이고
두번째 input
에 변경이 발생하면 [name]
에 nickname
이 들어간다.
만약 [name]
을 안쓰고 작성하신 것처럼 name
만 있으면 nickname
에 대한 값은 업데이트 되지 않는다.
그리고 inputs
객체를 복사하는 이유가 spread
문법을 쓰지 않는다면 두개의 input
태그중에 하나만 변경이 일어났을때 onChange
함수에서 setInputs({ nickname : 'aaa'})
를 호출할 것이다.
이건 useState
를 통해 초기화햇던 객체랑 구조가 다르게 되니 문제가 생기는 것
기존 input
객체를 복사해야 하는 이유는,
함수형 컴포넌트에서 상태를 업데이트할 때는 클래스형 컴포넌트와 다르게 값자체가 대체되기 때문이다.
이 글은 패스트캠퍼스 '프론트엔드(React)올인원패키지Online'을 수강하며 정리한 노트입니다.
https://fastcampus.co.kr/search?keyword=%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C