React가 폼의 값을 제어하는걸 제어컴포넌트라고 한다.
HTML에서 input, textarea, select와 같은 폼 엘리먼트는 자신의 state를 관리하고 업데이트한다.
React에서는 React가 state와 setState로 관리한다.
<form onSubmit={this.handleSubmit}>
<label>
Name:
<input type="text" value={state} onChange={handleChange} />
</label>
<input type="submit" />
</form>
value 어트리뷰트는 값은 state가 되고 onChange를 통해 값을 변경한다.
HTML에서 textarea 엘리먼트는 텍스트를 자식으로 정의합니다.
<textarea>
Hello there, this is some text in a text area
</textarea>
react에서는 value 어트리뷰트로 자식을 정의
<textarea value={state} onChange={handleChange} />
html에서 selected 옵션이 붙으면 초기값이 된다
<select>
<option value="grapefruit">Grapefruit</option>
<option value="lime">Lime</option>
<option selected value="coconut">Coconut</option>
<option value="mango">Mango</option>
</select>
react에서는 최상단 select태그에 value 어트리뷰트를 사용
<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>
<input type="file" />
값이 읽기 전용이기 때문에 React에서는 비제어 컴포넌트다
const [state, setState] = useState({
isGoing: true,
numberOfGuests: 2
})
const handleInputChange = (event)=> {
const target = event.target;
const value = target.type === 'checkbox' ? target.checked : target.value;
const name = target.name;
setState((prev))=>{
return {...prev, [name] = value}
})
}
<form>
<label>
Is going:
<input
name="isGoing"
type="checkbox"
checked={state.isGoing}
onChange={handleInputChange} />
</label>
<br />
<label>
Number of guests:
<input
name="numberOfGuests"
type="number"
value={state.numberOfGuests}
onChange={handleInputChange} />
</label>
</form>
제어 컴포넌트는 사용자가 입력한 값과 저장되는 값이 실시간으로 동기화된다
비제어 컴포넌트는 값이 실시간으로 동기화 되지 않는다.
제어컴포넌트의 문제점이 입력마다 랜더링이 발생한다. 불필요한 랜더링을 막기위해 스로틀링이나 디바우싱을 사여ㅛㅇ한다.
| 기능 | 제어 컴포넌트 | 비제어 컴포넌트 |
|---|---|---|
| 일회성 정보 검색 (예: 제출) | O | O |
| 제출 시 값 검증 | O | O |
| 실시간으로 필드값의 유효성 검사 | O | X |
| 조건부로 제출 버튼 비활성화 (disabled) | O | X |
| 실시간으로 입력 형식 적용하기 (숫자만 가능하게 등) | O | X |
| 동적 입력 | O | X |