본문 바로가기
개발

[ReactJS] 입력폼(Forms)

by 마스터누누 2017. 6. 13.
728x90
반응형

입력폼(Forms)



1
2
3
4
5
6
7
<form>
  <label>
    Name:
    <input type="text" name="name" />
  </label>
  <input type="submit" value="Submit" />
</form>
cs


HTML의 폼 엘리먼트는 자연스럽게 내부상태를 유지하기 때문에, 리액트와 조금 다른 방식으로 동작한다.

예를 들어, 일반 HTML 형식의 양식은 단일 이름을 허용한다.

이와 같은 코드를 리액트에서 사용한다면 동일하게 동작은 한다.

그러나 대부분의 경우 form 데이터를 처리하고 

사용자가 form에 입력한 데이터에 액세스 할 수 있는 자바스크립트 기능을 가지는 것이 더 편리하다

이를 위해 controlled component 를 사용한다.





Controlled Component


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
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>
    );
  }
}
cs


HTML 에서 <input>,<textarea>,<select>와 같은 form 엘리먼트는 

일반적으로 자체 상태를 유지하고 사용자 입력을 기반으로 업데이트된다.

리액트에서는 변경할수 있는 state가 일반적으로 컴포넌트의 state의 속성에 유지 되며 setState()만 업데이트된다.


우리는 리액트의 state를 "single source of truth"로 만들어 두 엘리먼트를 결합할 수 있다.

그런다음 form을 랜더링 하는 리액트 컴포넌트는 추후 사용자 입력시 해당 form 에서 일어나는 일을 제어한다.

이러한 방식으로 리액트에 의해 제어되는 form 엘리먼트를 Controlled Component라고 한다.


예를 들어 위의 코드에서 처럼 이전 예제가 제출 될 때 이름을 기억되도록 하려면,

controlled component로 form을 작성할 수 있다.


value 속성은 form 엘리먼트에 설정되어 있으므로 표시된 값은 

항상 this.state.value가 되어 리액트 state가 single truth가 된다.

리액트 state를 업데이트 하기 위해 모든 키 입력에서 handleChange가 실행되기 때문에

사용자가 입력할 때 마다 표시된 값이 업데이트 된다.





<textarea> 태그


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
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>
          Name:
          <textarea value={this.state.value} onChange={this.handleChange} />
        </label>
        <input type="submit" value="Submit" />
      </form>
    );
  }
}
 
cs


HTML에는 <textarea></textarea> 사이에 있는 글자가 페이지에 출력된다.

JSX에서는 <textarea />의 value로 페이지에 출력되는 글자를 전달한다.





<select> 태그


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
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 La Croix 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>
    );
  }
}
cs


HTML에서 <select>는 <option>과 결합하여 드롭다운 메뉴를 만든다.

<select>에서 제일 최상단의 option이 초기 select 메뉴로 지정되는데, 

리액트는 이와 다르게 select에 value로 전달된 값이 초기 select 메뉴가 된다.

따라서 한곳만 업데이트하면 되기 때문에 controlled component에서 더 편리하다


전반적으로 이렇게하면 <textarea>와 <select>는 매우 유사하게 작동한다.

두 태그는 모두 controlled component를 구현하는데 사용될 수 있는 값 속성을 허용한다.





다중 입력 처리


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
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>
    );
  }
}
cs


여러개의 입력 엘리먼트를 처리해야 하는 경우 각 엘리먼트에 name 속성을 추가하고 

event.target.name의 값에 따라 수행할 작업을 선택하게 할 수 있다.



반응형

댓글