html 폼 엘리먼트는 엘리먼트 자체가 내부 상태를 가지기 때문에
React의 다른 DOM 엘리먼트와 다르게 동작한다
기본 폼 형태
<form>
<label>
Name:
<input type="text" name="name" />
</label>
<input type="submit" value="Submit" />
</form>
리액트에서 위와 같은 동작을 원한다면 그대로 사용할 수 있다
하지만 대부분의 경우 자바스크립트 함수로 폼의 제출을 처리하고
사용자가 폼에 입력한 데이터에 접근하도록 하는 것이 편리하다
이를 위한 표준 방식은 제어 컴포넌트라는 기술을 이용한다
html 에서 input, textarea, select 와 같은 폼 엘리먼트는
사용자 입력을 기반하여 자신의 state를 관리하고 업데이트 한다
리액트에서는 변경할 수 있는 state가 일반적으로
컴포넌트 속성에 유지되고 setState()에 의해 업데이트 된다
state를 신뢰 가능한 단일 출처로 만들어 두 요소를 결합할 수 있다
그러면 폼을 렌더링하는 컴포넌트는 폼에 발생하는 사용자 입력값을 제어한다
리액트에 의해 값이 제어되는 입력 폼 엘리먼트를 제어 컴포넌트라고 한다
<form onSubmit={this.handleSubmit}>
<label>
Name:
<input type="text" value={this.state.value} onChange={this.handleChange} />
</label>
<input type="submit" value="Submit" />
</form>
textarea는 text를 자식으로 받는다
<textarea value={this.state.value} onChange={this.handleChange} />
<select value={this.state.value} onChange={this.handleChange}>
<option value="grapefruit">Grapefruit</option>
<option value="lime">Lime</option>
<option value="coconut">Coconut</option>
<option value="mango">Mango</option>
</select>
select 태그에 multiple 옵션을 허용하면 value 어트리뷰트에 배열을 전달할 수 있다
<input type="file" />
하나 이상의 파일을 저장소에서 서버로 업로드 하거나
file API를 통해 자바스크립트로 조작할 수 있다
값이 읽기 전용이기 때문에 비제어 컴포넌트다
하나의 eventHandler 함수를 통해
여러 input 이벤트를 관리할 경우
name으로 구분하여 상태를 관리할 수 있다
handleInputChange(event) {
const target = event.target;
const value = target.type === 'checkbox' ? target.checked : target.value;
const name = target.name;
var partialState = {};
partialState[name] = value;
this.setState(partialState);
}
<form>
<label>
Is going:
<input
name="isGoing"
type="checkbox"
checked={this.state.isGoing}
onChange={this.handleInputChange} />
</label>
<br />
<label>
Number of guests:
<input
name="numberOfGuests"
type="number"
value={this.state.numberOfGuests}
onChange={this.handleInputChange} />
</label>
</form>
제어 컴포넌트에 value prop을 지정하면 의도하지 않는 한 변경할 수 없다
실수로 undefined나 null을 줬을 경우에는 예외다
ReactDOM.createRoot(mountNode).render(<input value="hi" />);
setTimeout(function() {
ReactDOM.createRoot(mountNode).render(<input value={null} />);
}, 1000);
비제어 컴포넌트로 임력 폼을 구현할 수도 있다
리액트는 Formik을 추천하지만
최근 대세는 react hook form 인 것 같다