React 공식문서 정독하기 - 3. FORM

kind J·2022년 6월 6일
0

React 공식문서

목록 보기
3/3
post-thumbnail

HTML 폼 엘리먼트는 폼 엘리먼트 자체가 내부 상태를 가지기 때문에, React의 다른 엘리먼트와 다르게 동작한다. 순수한 HTML 에서 이 폼은 name 을 입력받는다.

<form>
  <label>
    Name:
    <input type="text" name="name" />
  </label>
  <input type="submit" value="Submit" />
</form>

이 폼은 사용자가 폼을 제출하면 새로운 페이지로 이동하는 기본 HTML 폼 동작을 수행한다.
리액트에서 동일한 동작을 원한다면 그대로 사용하면된다.

그러나 대부분의 경우 JS 함수로 폼을 제출을 처리하고 사용자가 폼에 입력한 데이터에 접근하도록 하는 것이 편리하다. 이를 위한 표준 방식은 “제어 컴포넌트 (controlled components)“라고 불리는 기술을 이용하는 것이다.

제어컴포넌트(Controlled Component)

HTML에서 input, textarea, select와 같은 폼 엘리먼트는 일반적으로 사용자의 입력을 기반으로 자신의 state를 관리하고 업데이트한다. React에서는 변경할 수 있는 state가 일반적으로 컴포넌트의 state 속성에 유지되며 setState()에 의해 업데이트된다.

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>
    );
  }
}

제어 컴포넌트로 사용하면, input의 값은 항상 React state에 의해 결정된다. 코드를 조금 더 작성해야 한다는 의미이지만, 다른 UI 엘리먼트에 input의 값을 전달하거나 다른 이벤트 핸들러에서 값을 재설정할 수 있다.

textarea 태그

HTML 에서 textarea는 텍스트를 자식으로 정의한다.

<textarea>
  Hello there, this is some text in a text area
</textarea>

리액트에서 textarea는 value 어트리뷰트를 대신 사용한다.
this.state.value를 생성자에서 초기화하므로 textarea는 일부 텍스트를 가진채 시작되는 점을 주의해야한다.

select 태그

HTML 에서 select 는 드롭다운 목록을 만든다.

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>
    );
  }
}

전반적으로

<input type="text">
<textarea>
<select>

모두 매우 비슷하게 동작한다. 모두 제어 컴포넌트를 구현하는데 value 어트리뷰트를 허용한다.

select 태그에 multiple 옵션을 허용한다면 value 어트리뷰트에 배열을 전달할 수 있다.

file input 태그

html 에서 input type="file" 는 사용자가 하나 이상의 자신의 장치 저장소에서 서버로 업로드하거나 File API 를 통해 Javascript 로 조작할 수 있다.

File API 참고링크)
https://developer.mozilla.org/ko/docs/Web/API/File_API/Using_files_from_web_applications
참고링크)
https://ko.reactjs.org/docs/uncontrolled-components.html#the-file-input-tag

<input type="file" />

값이 읽기 전용이므로 React 에서는 [비제어 컴포넌트] 이다.

다중 입력 제어하기

여러 input 엘리먼트를 제어할 때 각 엘리먼트에 name 어트리뷰트를 추가하고
event.target.name 값을 통해 핸들러가 어떤 작업을 할 수 있을지 선택할 수 있게 해준다.

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>
    );
  }
}
profile
프론트앤드 개발자로 일하고 있는 kind J 입니다.

0개의 댓글