form element는 내부 state를 갖고있기 때문에
HTML form 은 다른 DOM element와는 약간 다르게 작동한다.
예를 들면, 이 form은 한개의 이름을 받는다.
<form>
<label>
Name:
<input type="text" name="name" />
</label>
<input type="submit" value="Submit" />
</form>
이것을 React에 그대로 써도 작동은 하지만 대게 javascript function을 가지고 있으면 편리하다. 이를 위한 기술을 'controlled components'라고 한다.
React에서는 보통 변할 수 있는 state가 component의 state property에 저장되고,setState()로만 업데이트된다.
React state를 'single source of truth'로 만듦으로써 두개를 조합할 수 있다. 그러면 form을 render하는 React component는 뒤따르는 user input에 무엇이 일어날지 컨트롤한다. 이런 방식으로 React에 의해서 그 값이 컨트롤되는 input form element는 'controlled component'라고 불린다.
예제
class NameForm extends React.Component {
constructor(props) {
super(props);
this.state = {value: ''};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(event) {
this.setState({value: event.target.value});
}
handleSubmit(event) {
alert('A name was submitted: ' + this.state.value);
event.preventDefault();
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<label>
Name:
<input type="text" value={this.state.value} onChange={this.handleChange} />
</label>
<input type="submit" value="Submit" />
</form>
);
}
}
handleChange가 키를 누를때마다 React state를 업데이트 시키기 때문에 사용자가 입력할 때마다 보여지는 값이 업데이트된다.
<textarea>
Hello there, this is some text in a text area
</textarea>
React에서는 textarea는 attribute값을 사용한다. 이를 이용해서,<textarea>를 쓰면 한줄 input을 사용하는 form과 유사하게 만들 수 있다.
class EssayForm extends React.Component {
constructor(props) {
super(props);
this.state = {
value: 'Please write an essay about your favorite DOM element.'
};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(event) {
this.setState({value: event.target.value});
}
handleSubmit(event) {
alert('An essay was submitted: ' + this.state.value);
event.preventDefault();
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<label>
Essay:
<textarea value={this.state.value} onChange={this.handleChange} />
</label>
<input type="submit" value="Submit" />
</form>
);
}
}
2.The select Tag
예제
class FlavorForm extends React.Component {
constructor(props) {
super(props);
this.state = {value: 'coconut'};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(event) {
this.setState({value: event.target.value});
}
handleSubmit(event) {
alert('Your favorite flavor is: ' + this.state.value);
event.preventDefault();
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<label>
Pick your favorite flavor:
<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>
</label>
<input type="submit" value="Submit" />
</form>
);
}
}
select tag에 multiple 옵션을 넣어서 value attribute로 배열을 넣을 수 있다.
<select multiple={true} value={['B', 'C']}>
<input type="file" />
value가 readonly이기 때문에 React component로 조작이 불가능
여러개의 input을 다루어야할 때, name attribute를 더할 수 있다. 그래서 event.target.name의 값을 이용해 handler function이 선택할 수 있게 할 수 있다.
예제
class Reservation extends React.Component {
constructor(props) {
super(props);
this.state = {
isGoing: true,
numberOfGuests: 2
};
this.handleInputChange = this.handleInputChange.bind(this);
}
handleInputChange(event) {
const target = event.target;
const value = target.type === 'checkbox' ? target.checked : target.value;
const name = target.name;
this.setState({
[name]: value });
}
render() {
return (
<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>
);
}
}
예제 (이 input은 처음에는 잠겨있지만 조금의 딜레이 후에 수정 가능해진다.)
ReactDOM.render(<input value="hi" />, mountNode);
setTimeout(function() {
ReactDOM.render(<input value={null} />, mountNode);
}, 1000);
*mountNode 란 : document.getElementById('root') 같은 것..