이제 컴포넌트로 주입된 데이터를 기반으로 컴퍼넌트에 기본적으로 입력되는 값을 세팅해보자.
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.js
import 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);
// ...
}
위 코드를 추가하여 깔끔하게 코드를 만드는 리팩토링을 한 것이다.