form

y0ung·2020년 12월 16일
0

React

목록 보기
9/13
post-thumbnail

React에서는 조금 다르게 form을 처리한다. 이를 위한 표준 방식은 "제어 컴포넌트"라고 불리는 기술이다.

제어 컴포넌트(Controlled Component)

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

React state를 신뢰 가능한 단일 출처로 만들어 두 요소를 결합할수 있다. 폼을 렌더링하는 React컴포넌트는 폼에 발생하는 사용자 입력값을 제어한다. 이러한 방식으로 React에 의해 값이 제어되는 입력 폼 엘리먼트를 제어 컴포넌트 라고 한다.

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>
        <button type="submit">Submit</button>
      </form>
    );
  }
}

제어 컴포넌트로 사용하면, input의 값은 항상 React state에 의해 결정된다. 다른 UI엘리먼트에 input의 값을 전달하거나 다른 이벤트 핸들러에 서 값을 재설정 할 수 있다.

<textarea>

React에서 <textarea>는 value 어트리뷰트를 대신 사용한다.. 이렇게하면 <textarea>를 사용하는 폼은 한 줄 입력을 사용하는 폼과 비슷하게 작성할 수 있다.

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

this.state.value를 생성자에서 초기화하므로 textarea는 일부 텍스트를 가진채 시작되는 점을 주의!

<select>

React에서는 selected 어트리뷰트를 사용하는 대신 최상단 select태그에 value 어트리뷰트를 사용. 한 곳에서 업데이트만 하면되기 때문에 제어 컴포넌트에서 사용하기 더 편하다.

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 태그에 multiple 옵션을 허용할때 value 어트리뷰트에 배열을 전달할 수 있다.

<select multiple={true} value={['b','c']}>	

<input type"file">

HTML에서 <input type"file">는 사용자가 하나 이상의 파일을 자신의 장치 저장소에서 바로 업로드 하고나 File API를 통해 JavaScript로 조작할 수 있다.

값이 읽기 전용이기 때문에 React에서는 비제어 컴포넌트 이다.

다중 입력 제어하기

여러 input엘리먼트를 제어해야할 때, 각 엘리먼트에 name 어트리 뷰트를 추가하고 e.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>
    );
  }
}  

주어진 input 태그의 name에 일치하는 state를 업데이트하기 위해 ES6의 computed property name 구문을 사용.

this.setState({
  [name]: value
});

ES5 코드

let partialState = {};
partialState[name] = value;
this.setState(partialState);

setState()는 자동적으로 현재 state에 일부 state를 병합하기 때문에 바뀐 부분에 대해서만 호출하면 된다.

제어 되는 input Null 값

제어 컴포넌트에서 value prop을 지정하면 의도하지 않는 한 사용자가 변경할수 없다. value를 설정했는데 여전히 수정할 수 있다면 실수로 value를 undefinednull로 설정했을 수 있다.

ReactDOM.render(<input value="hi" />, mountNode);

setTimeout(function() {
  ReactDOM.render(<input value={null} />, mountNode);
}, 1000);

참고

해당 포스팅은 실전 리엑트 공식 홈페이지 https://ko.reactjs.org/
리엑트 자습서 https://ko.reactjs.org/docs/forms.html 에서 참고하여 작성했습니다.

profile
어제보다는 오늘 더 나은

0개의 댓글