이제 컴포넌트로 주입된 데이터를 기반으로 컴퍼넌트에 기본적으로 입력되는 값을 세팅해보자.
UpdateContent.js 파일로 들어온 데이터는 _content 변수를 통해 들어 있는 상태다.
UpdateArti.js>render><form>영역/* *기존 <p> <input type="text" name="title" placeholder="title"></input> </p> <p> <textarea name="desc" placeholder="description"></textarea> </p> <p> <input type="submit"></input> </p> */ /** 수정 */ <p> <input type = "text" name = "title" placeholder = "title" value={this.props.title} ></input> </p>
위 코드를 추가한 뒤 업데이트 버튼을 클릭할 때 정상 작동하지 않고 경고 문구가 나오는 것을 확인할 수 있다.
그 내용은 props 를 직접 value 에 넣을 때 onChange 라고 불리는 핸들러를 사용하지 않으면 read-only 가 된다고 적혀있다.
value 값으로 컴포넌트 안에서 가변적인 데이터를 state화를 시켜줘야 한다.
아래와 같이 코드를 추가하자.
UpdateArti.jsimport React, { Component } from 'react'; class UpdateArti extends Component { // constructor 함수 생성 constructor(props){ super(props); this.state = { titls:this.props.data.title } } // <input> 태그 수정 <input type = "text" name = "title" placeholder = "title" value = {this.state.title} </input>
input value 의 state가 내용을 수정하더라도 state 상태가 바뀌어야 되는 근거는 없기 때문에 여전히 수정되지 않는다.
input 값을 바꿨을 때 state 값을 바뀌게 해야 read-only 상태가 아니게 된다.
그래서 onChange 를 꼭 작성해야 한다.
UpdateArti.js>render><form>영역<p> <input type = "text" name = "title" placeholder = "title" value={this.props.title} onChange={function(e){ console.log(e.target.value); }.bind(this)} ></input> </p>
이벤트가 발생할 때 마다 어떤 값이 들어오는지 콘솔을 통해 확인해보자.
- console 창
e.target.value 는 이벤트의 타겟인 input 태그의 value 값을 의미한다.
업데이트할 때마다 한글자씩 바뀌는 value 값들을 컴포넌트의 state 값에 바로 동기화를 시켜주도록 작성한다.
UpdateArti.js>render><form>영역<p> <input type = "text" name = "title" placeholder = "title" value={this.props.title} onChange={function(e){ this.setState({title : e.target.value }); }.bind(this)} ></input> </p>
이제 업데이트 할 때 리액트 컴포넌트의 state 를 보면 내용을 바꾸는 것에 따라서 state 가 동적으로 바뀌는 것을 볼 수 있습니다.
<textarea> 태그도 처리해보자.
// constructor 함수 constructor(props){ super(props); this.state = { title : this.props.data.title, desc : this.props.data.desc } } - - - // <textarea> 태그 수정 <textarea onChange={function(e){ this.setState({title : e.target.value }); }.bind(this)} name = "desc" placeholder = "description" value = {this.state.desc}></textarea>
위 코드는 html처럼 보이지만 html이 아닌 리액트의 HTML이다.
리액트는 value를 추가해야 한다.
해당 코드를 실행하면 잘 동작하는 것을 확인할 수 있지만... 이런 식으로 하나하나 onChange 를 만들기 번거롭다.
그래서 inputFormHandler 라는 이름의 함수를 만들어서 중복을 제거해 준다.
// inputFormHander 함수 추가 inputFormHandler(e){ this.setState({title : e.target.value}); } // onChange 이벤트 내용 변화 onChange = {this.inputFormHandler.bind(this)}
업데이트를 했을 때 이전과 똑같지만 반복되는 코드를 밖으로 빼내면서 가독성이 더욱 좋아졌다.
하지만 inputFormHander 함수는 title이라고 정해져 있기 때문에 <textarea> 태그의 onChange 이벤트에서는 동일하게 사용할 수 없는 문제가 남아있다.
이것을 해결하기 위해서 고정된 title 을 이벤트가 발생하고 있는 태그의 이름의 무엇인지 알아내는 코드로 변경해주자.
inputFormHander(e){
this.setState({[e.target.name]:e.target.value});
<input>태그와 <textarea> 태그 모두 잘 동작하는 걸 확인할 수 있다.
하지만 bind(this) 를 계속 추가해줘야 하는 불편함이 남아있다.
constructor(props){
this.inputFormHandler = this.inputFormHandler.bind(this);
// ...
}
위 코드를 추가하여 깔끔하게 코드를 만드는 리팩토링을 한 것이다.