Skip to content

6. Form

forjjy edited this page Nov 30, 2016 · 11 revisions

Forms

React 에서의 Form은 HTML의 Form과 비슷합니다. 하지만, 아래 코드는 실행하면 Input 필드에 값이 입력되지 않습니다.

var Text = React.createClass({
  getInitialState() {
    return {
      textValue: "initial value"
    };
  },
  render() {
    return (
      <div>
	<p>{this.state.textValue}</p>
	<input type="text" value={this.state.textValue} />
      </div>
    );
  }
});

ReactDOM.render(
  <Text />,
  document.getElementById('root')
);

Controlled Components

Controlled Component는 State에 따라 값을 관리하는 Componenet 입니다.(single source of truth) 위에서 입력되지 않는 부분을 아래처럼 setState를 이용하여 입력값이 반영될 수 있게 수정한 코드입니다.

var Text = React.createClass({
  getInitialState() {
    return {
      textValue: "initial value"
    };
  },
  changeText(e) {
    this.setState({textValue: e.target.value});
  },
  render() {
    return (
      <div>
	<p>{this.state.textValue}</p>
	<input type="text" value={this.state.textValue} onChange={this.changeText} />
      </div>
    );
  }
});

ReactDOM.render(
  <Text />,
  document.getElementById('root')
);

value를 State로 관리하고, onChange()에서 setState()하여 명시적으로 값을 갱신하고 전달합니다.

UnControlled Component

UnControlled Componenent는 반대로 값을 관리하지 않는 컴포넌트로 초기값을 설정한 값은 defaultValue로 지정합니다. 이 경우는 앞 절에서처럼 onChange()에서 항상 값을 state에 반영해도 되고, 반영하고 싶을 때만 DOM에서 value를 취득하여 갱신하는 것도 가능합니다.

var LiveText = React.createClass({
  getInitialState() {
    return {
      textValue: "initial value"
    };
  },
  changeText(e) {
    this.setState({textValue: this.refs.inputText.getDOMNode().value });
  },
  render() {
    return (
      <div>
	<p>{this.state.textValue}</p>
	<input type="text" ref="inputText" defalutValue="initial value" />
	<button onClick={this.changeText}>change</button>
      </div>
    );
  }
});

ReactDOM.render(
  <LiveText />,
  document.getElementById('root')
);

Textarea

textarea의 경우도 텍스트 필드와 마찬가지로 value를 지정합니다. HTML 처럼 <textarea>xxx</textarea> 으로 작성하면 xxx는 defaultValue로 취급됩니다.

var OreTextArea = React.createClass({
  getInitialState() {
    return {
      textAreaValue: 'initial value'
    };
  },
  onChangeText(e) {
    this.setState({textAreaValue: e.target.value});
  },
  onClick() {
    this.setState({textAreaValue: this.refs.textArea.getDOMNode().value});
  },
  render() {
    return (
      <div>
	<div>{this.state.textAreaValue}</div>
	<div>
	  <textarea value={this.state.textAreaValue} onChange={this.onChangeText} />
	</div>
	<div>
	  <textarea ref="textArea">this is default value</textarea>
	  <button onClick={this.onClick}>change</button>
	</div>
      </div>
    );
  }
});

ReactDOM.render(
  <OreTextArea />,
  document.getElementById('root')
);

SelectBox

셀렉트 박스도 역시 value를 지정합니다. multiple={true}와 같이 Prop을 지정하면 요소를 복수로 선택할 수 있습니다.

var OreSelectBox = React.createClass({
  getDefaultProps: function() {
    return {
      answers: [1, 10, 100, 1000]
    };
  },
  getInitialState: function() {
    return {
      selectValue: 1,
      selectValues: [1,100]
    };
  },
  onChangeSelectValue: function(e) {
    this.setState({selectValue: e.target.value});
  },
  onChangeSelectValues: function(e) {
    var values = _.chain(e.target.options)
      .filter(function(option) { return option.selected })
      .map(function(option) { return +option.value })
      .value()
    ;
    this.setState({selectValues: values});
  },
  render: function() {
    var options = this.props.answers.map(function(answer) {
      return <option value={answer} key={answer}>{answer}</option>;
    });
    return (
      <div>
	<div>selectValue: {this.state.selectValue}</div>
	<div>
	  <select value={this.state.selectValue} onChange={this.onChangeSelectValue}>
	    {options}
	  </select>
	</div>
	<div>selectValues: {this.state.selectValues.join(",")}</div> 
	<div>
	  <select multiple={true} defaultValue={this.state.selectValues} onChange={this.onChangeSelectValues}>
	    {options}
	  </select>
	</div>     
      </div>
    );
  }
});
 
React.render(<OreSelectBox />, document.body);

#LinkedStateMixin. --> ES6에서는 mixin을 지원하지 않기 때문에 동작하지 않을 듯 합니다. LinkedStateMixin이라는 addon을 사용하면 앞에서 처럼 onChange()를 일일이 구현하지 않아도 state에 반영할 수 있습니다. 체크박스에 사용할 때는 checkLink를 사용합니다.

var React = require('react/addons');
var LinkedStateMixin = React.createClass({
  mixins: [React.addons.LinkedStateMixin],
  getInitialState() {
    return {
      textValue: 'initial value'
    }
  },
  render() {
    return (
      <div>
	<div>value: {this.state.textValue}</div>
	<input type="text" valueLink={this.linkState('textValue')} />
      </div>
    );
  }
});

React.render(<LinkedStateMixin />, document.body);

Clone this wiki locally