4.2 예제로 이벤트 핸들링 익히기

4.2.1.1 컴포넌트 생성

//EventPractice.js

import React, {Component} from 'react';

    class EventPractice extends Component {
      render() {
          return (
              <div>
                  <h1>이벤트 연습</h1>
              </div>
          )
      }  
    }

export default EventPractice;

4.2.2.2 state에 input 값 담기

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);}

4.2.2.1 onChange 이벤트 설정

  1. constructor에서 state 초깃값 설정
  2. 이벤트 핸들링 함수 내부에서 this.setState 메서드 호출(state 업데이트)
  3. input의 value 값을 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>
                 </>
             )
         }
      }  

export default EventPractice;

오류 발생이 아닌 제대로 입력된다면 state에 텍스트를 잘 담은것이다.

4.2.2.3 버튼 누를 때 comment 값을 공백으로 설정

입력한 값이 state에 잘 들어갔는지, 인풋에서 제대로 반영하는지 확인하기 위해 세 가지의 작업을 진행하자.

  1. input 요소 코드 아래쪽에 button을 만든다.
  2. 클릭 이벤트가 발생하면 현재 comment 값을 메시지 박스로 띄운다.
  3. comment 값을 공백으로 설정한다.
//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;

4.2.3 임의 메서드 만들기

함수를 미리 준비해 전달하면 성능상으론 차이가 없지만 가독성은 높다.(상황에 따라 렌더링 메서드 내부에서 함수를 만드는게 더 편할때도 있다.)

onChange와 onClick에 전달한 함수를 따로 빼 컴포넌트 임의 메서드를 만들어보자

4.2.3.1 기본 방식

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를 가리키게 된다.

4.2.3.2 Property Initializer Syntax를 사용한 메서드

메서드 바인딩은 생성자 메서드에서 하는 것이 정석이지만 메서드를 만들 때마다 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;

좋은 웹페이지 즐겨찾기