//EventPractice.js
import React, {Component} from 'react';
class EventPractice extends Component {
render() {
return (
<div>
<h1>이벤트 연습</h1>
</div>
)
}
}
export default EventPractice;
EventPractice 컴포넌트에 input 요소를 렌더링하는 코드와 해당 요소에 onChange 이벤트 설정하는 코드 작성하고 EventPractice 컴포넌트의 render 메서드에 작성하자
//EventPractice.js
import React, {Component} from 'react';
class EventPractice extends Component {
render() {
return (
<div>
<h1>이벤트 연습</h1>
<input
type="text"
name="message"
placeholder="아무거나"
onChange={
(e) => {
console.log(e);
}
}
/>
</div>
)
}
}
export default EventPractice;
👇 console 결과물
💡 EventPractice.js의 onChange 설정 부분 다시 보기
onChange={(e) => {console.log(e);}
콘솔에 기록되는 e 객체는 SyntheticEvent로 웹 브라우저의 네이티브 이벤트를 감싸는 객체이다. 네이티브 이벤트와 인터페이스가 같아 순수 자바스크립트에서 HTML 이벤트를 다룰 때와 같이 사용하면된다. 하지만 SyntheticEvent는 네이티브 이벤트와 달리 이벤트가 끝나고나면 초기화돼 정보를 참조할 수 없다. 예를 들어, 0.5초 뒤에 e 객체를 참조하면 e 객체 내부의 모든 값이 비워지가 된다. (비동기적으로 이벤트 객체를 참조하려면 e.persist() 함수를 호출해야한다)
예를 들어 onChange 이벤트가 발생할 때, 변할 인풋 값인 e.target.value를 콘솔에 기록하겠다
💡 EventPractice.js의 onChange 코드 수정
onChange={(e) => {console.log(e.target.value);}
//EventPractice.js
import React, {Component} from 'react';
class EventPractice extends Component {
state = {
message: ''
}
render() {
return (
<>
<h1>연습</h1>
<input
type= "text"
name= "message"
placeholder= "아무거나"
value={this.state.message}
onChange= {
(e) => {
this.setState({
message: e.target.value
})
}
}
>
</input>
</>
)
}
}
export default EventPractice;
오류 발생이 아닌 제대로 입력된다면 state에 텍스트를 잘 담은것이다.
입력한 값이 state에 잘 들어갔는지, 인풋에서 제대로 반영하는지 확인하기 위해 세 가지의 작업을 진행하자.
//EventPractice.js
import React, {Component} from 'react';
class EventPractice extends Component {
state = {
message: ''
}
render() {
return (
<>
<h1>연습</h1>
<input
type= "text"
name= "message"
placeholder= "아무거나"
value={this.state.message}
onChange= {
(e) => {
this.setState({
message: e.target.value
})
}
}
>
</input>
<button onClick= {
() => {
alert(this.state.message)
this.setState({
message:''
})
}
}>
확인
</button>
</>
)
}
}
export default EventPractice;
함수를 미리 준비해 전달하면 성능상으론 차이가 없지만 가독성은 높다.(상황에 따라 렌더링 메서드 내부에서 함수를 만드는게 더 편할때도 있다.)
onChange와 onClick에 전달한 함수를 따로 빼 컴포넌트 임의 메서드를 만들어보자
EventPractice .js
import React, {Component} from 'react';
class EventPractice extends Component {
state = {
message: ''
}
constructor(props){
super(props);
this.handleChange = this.handleChange.bind(this);
this.handleClick = this.handleClick.bind(this);
}
handleChange(e){
this.setState({
message: e.target.value
});
}
handleClick(){
alert(this.state.message);
this.setState({
message: ''
});
}
render() {
return (
<>
<h1>연습</h1>
<input
type= "text"
name= "message"
placeholder= "아무거나"
value={this.state.message}
onChange= {this.state.handleChange}
>
</input>
<button onClick= {this.handleClick}>확인</button>
</>
)
}
}
export default EventPractice;
함수가 호출될 때 this는 호출부에 따라 결정되므로, 클래스의 임의 메서드가 특정 HTML 요소의 이벤트로 등록되는 과정에서 메서드와 this의 관계가 끊어진다. 이 때문에 임의 메서드가 이벤트로 등록되어도 this를 컴포넌트 자신으로 제대로 가리키기 위해서는 메서드를 this와 바인딩(binding)하는 작업이 필요하다. 만약 바인딩하지 않는 경우라면 this가 undefined를 가리키게 된다.
메서드 바인딩은 생성자 메서드에서 하는 것이 정석이지만 메서드를 만들 때마다 constructor도 수정해야하기 때문에 불편하다고 느낄 수 있다. 그렇기 때문에 좀 더 간단한 방법은 바벨의 transform-class-properties 문법을 사용해 화살표 함수 형태로 메서드를 정리하는 것이다.
import React, {Component} from 'react';
class EventPractice extends Component {
state = {
message: ''
}
handleChange = (e) => {
this.setState({
message: e.target.value
});
}
handleClick = () => {
alert(this.state.message);
this.setState({
message:''
})
}
render() {
return (
<>
<h1>연습</h1>
<input
type= "text"
name= "message"
placeholder= "아무거나"
value={this.state.message}
onChange= {this.handleChange}
>
</input>
<button onClick= {this.handleClick}>확인</button>
</>
)
}
}
export default EventPractice;