겪었던 문제들

react.js를 처음 접하여 input폼을 다루다보니 아래와같은 오류메세지를 자주보게된다.

Warning: Failed propType: You provided a `value` prop to a form field without an `onChange` handler. This will render a read-only field. If the field should be mutable use `defaultValue`. Otherwise, set either `onChange` or `readOnly`. Check the render method of `BasicCalculator`.

effec434565487.png

구글링을 해보니 폼에 대해서 다음과 같은 설명을 보게 되었다.

React는 컴포넌트 객체의 상태를 props와 state, 2가지로 구분해서 관리한다. React 문서에 나온 내용에 따르면 props는 컴포넌트를 생성할 때 사용자가 지정하는 일종의 설정 값이다. 이 값은 외부에서 넘겨받아 컴포넌트를 초기화 할 때 사용한다. 한 번 지정하고 나면 이 값은 변경할 수 없다. 물론 JavaScript 언어 특성상 코드 레벨에서 변경은 가능하지만 개발자 도구 콘솔에 경고 메시지가 뜨는 걸 볼 수 있다. 즉, 초기 설정 값을 보관하는 용도인 셈이다.

value값이 존재한다면 변해야하는 값과 변하지 말아야할 값에 대해서 좀더 조작해야할 필요가 있다.

해결법

변화되지 말아야할 값일때

<input type="number" value={this.state.result}/> 이런형태로 동적으로 값을 바꿀 수 있지만 value 속성이 들어가면 onChange이벤트를 넣던지 readOnly 속성을 넣어서 변화를 막아라고 경고를 준다.

<input type="number" value={this.state.result} readOnly/>

이렇게 변화되지 않게 readOnly속성을 넣어주면 더이상 경고가 뜨질 않는다.

변화되어야하는 값일때

변화되어야하는 폼이 들어갈때 단순히 value속성이 들어가면 경고가 뜨면서 이벤트를 걸었을때 정상적으로 작동되지 않는것을 볼 수 있을것이다.
단순히 경고를 회피하려면 아래와 같이 valuedefaultValue속성으로 바꿔주면 된다.

하지만 defaultValue={this.num}과같이 변수값을 주고 이벤트가 일어나면 변수값이 반영이 되지않는 값으로 계산한다. (input에서 다른값으로 고쳤지만 실질적으론 값이 변하지 않았음)
그래서 onChange이벤트속성을 이용하여 값이 변하면 이벤트 메서드를 실행하여 변수값에 대입해줘야한다.

var Foo = React.createClass({
   num : 0
   ,inputChange : function(event) {
      this.num = event.target.value;
   }
   ,render : function() {
      return (
         <input type="number" defaultValue={this.num} onChange={this.inputChange} />
      )
   }
});

테스트 컴포넌트 소스

// Count more plus
var AddCounter = React.createClass({
	incrementCount : function(){
		this.setState({
			count : this.state.count + 1
		});
		this.setProps({
			count : this.props.count + 5
		});
	},
	getInitialState : function(){
		return {
			count : 0
		}
	},
	render: function(){
		return (
			<div className="counter">
				<h1>{this.state.count}</h1>
				<h2>{this.props.count}</h2>
				<button type="button" onClick={this.incrementCount}>Increment</button>
			</div>
		)
	}
});

// Basic Calculator
var BasicCalculator = React.createClass({
	result : 0,
	inputValues : [4,5],
	getInitialState : function()
	{
		return {
			result : this.result,
			result2 : 0
		};
	},
	action : function(method)
	{
		switch(method)
		{
			case 'plus':
				this.result = this.inputValues[0] + this.inputValues[1];
				break;
			case 'subtraction':
				this.result = this.inputValues[0] - this.inputValues[1];
				break;
			case 'multiply':
				this.result = this.inputValues[0] * this.inputValues[1];
				break;
			case 'dividing':
				this.result = this.inputValues[0] - this.inputValues[1];
				break;
		}
		this.setState({
			result : this.result
		});
	},
	setInputvalue : function(key, event)
	{
		var number = parseInt(event.target.value);
		number = (number) ? number : 0;
		this.inputValues[key] = number;
	},
	render : function()
	{
		return (
			<form>
				<fieldset>
					<legend>기본 계산기</legend>
					<input type="number" defaultValue={this.inputValues[0]} onChange={this.setInputvalue.bind(null, 0)}/>
					<input type="number" defaultValue={this.inputValues[1]} onChange={this.setInputvalue.bind(null, 1)}/>
					<input type="number" value={this.state.result} readOnly />
				</fieldset>
				<nav className="nav text-center">
					<button type="button" onClick={this.action.bind(this, 'plus')}>더하기</button>
					&nbsp;
					<button type="button" onClick={this.action.bind(this, 'subtraction')}>빼기</button>
					&nbsp;
					<button type="button" onClick={this.action.bind(this, 'multiply')}>곱하기</button>
					&nbsp;
					<button type="button" onClick={this.action.bind(this, 'dividing')}>나누기</button>
				</nav>
			</form>
		);
	}
});

// render
React.render(<AddCounter count={2} />, document.getElementById('add-counter'));
React.render(<BasicCalculator />, document.getElementById('basic-calculator'));

메타데이터

조회수
5869
좋아요
9

0개의 댓글

등록된 댓글이 없습니다.