[React] 5. 이벤트 핸들링

🏃Dekay (JuniorDeveloper)·2021년 9월 21일
0

React

목록 보기
5/13
post-thumbnail

1. 이벤트 핸들링✨

  • 사용자가 웹 브라우저에서 DOM 요소들과 상호 작용하는 것을 이벤트(event)라고 한다.
  • 예를 들어, 버튼에 마우스 커서를 올렸을 때는 onmouseover, 클릭은 onclick, Form 요소는 값이 바뀔 때 onchange 이벤트를 실행한다.

1.1 리액트 이벤트 시스템

  • 리액트 이벤트 시스템은 웹 브라우저의 HTML 이벤트인터페이스가 동일하다.
  • 하지만, 주의해야 할 몇 가지가 있다.
  1. 이벤트 이름은 카멜 표기법으로 작성
    👉 예를 들어, HTML의 onclick리액트에서 onClick으로 작성해야 한다.
  2. 이벤트에 실행할 자바스크립트 코드를 전달하는 것이 아닌, 함수 형태의 값을 전달해야 한다.
    👉 HTML에서 이벤트를 설정할 때는 큰따옴표 안에 실행코드를 넣지만, 리액트함수 형태의 객체를 전달한다.
  3. DOM 요소에만 이벤트를 설정할 수 있다.
    👉 div, button, input, form, span 등의 DOM 요소에는 이벤트를 설정할 수 있지만, 생성한 컴포넌트에는 이벤트를 설정할 수 없다.

1.2 이벤트 핸들링 예제

  • 이벤트 핸들링을 실습하기 전에 src/EventPractice.js 파일을 생성하여 다음과 같은 코드를 작성했다.
//EventPractice.js
import React, { Component } from "react";

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

export default EventPractice;
  • 그 후, App.js 컴포넌트에서 EventPractice를 불러와 렌더링 했다.
//App.js
const App = () => {
  return <EventPractice />;
};

1.2.1 onChange 이벤트 핸들링

  • EventPractice 컴포넌트에 input 요소를 렌더링 하는 코드와 해당 요소에 onChange 이벤트 설정하는 코드는 아래와 같다.
//EventPractice
class EventPractice extends Component {
  render() {
    return (
      <div>
        <h1>이벤트 연습</h1>
        <input
          type="text"
          name="message"
          placeholder="입력하세요"
          onChange={(e) => {
            console.log(e);
          }}
        />
      </div>
    );
  }
}
  • input 요소에 아무것이나 입력하면 아래의 그림 처럼 이벤트 객체가 콘솔에 출력된다.

  • 콘솔에 기록되는 e 객체SyntheticEvent로 웹 브라우저의 네이티브 이벤트를 감싸는 객체이다.
  • 하지만, SyntheticEvent네이티브 이벤트와 달리 이벤트가 끝나면 초기화 된다.
    예를 들어, 0.5초 뒤에 e 객체를 참조하면 e 객체 내부의 모든 값이 지워진다.
  • 여기서 작성되는 글자를 출력하고 싶다면 console.log(e) => console.log(e.target.value)를 사용하면 된다. ✔

1.2.2 state에 input 값 담기

  • 앞서 배운 대로 생성자(constructor)state 초깃값을 설정하고, 이벤트 핸들링 함수 내부에서 this.setState 메서드를 호출하여 state를 업데이트를 해보자.
//EventPractice.js
class EventPractice extends Component {
  state = {
    message: "",
  };

  render() {
    return (
      <div>
        <h1>이벤트 연습</h1>
        <input
          type="text"
          name="message"
          placeholder="입력하세요"
          value={this.state.message}
          onChange={(e) => {
            this.setState({
                message: e.target.value
            })
          }}
        />
      </div>
    );
  }
}
  • 위의 코드를 통해 input 요소에 작성된 값을 state에 있는 값으로 설정할 수 있다.

1.2.3 버튼 클릭 시 comment 값을 공백으로 설정

  • 2.2.2 절에서 입력한 값이 state에 잘 들어갔는지 검증하기 위해서, input 요소 코드 아래쪽에 button을 하나 만들고 클릭 이벤트가 발생하면 현재 comment 값을 메세지 박스로 띄운 후 comment 값을 공백으로 설정하는 코드이다.
class EventPractice extends Component {
  state = {
    message: "",
  };

  render() {
    return (
      <div>
        <h1>이벤트 연습</h1>
        <input
          (...)
        />
        <button
          onClick={() => {
            alert(this.state.message);
            this.setState({
              message: "",
            });
          }}
        >확인</button>
      </div>
    );
  }
}

1.2.4 임의 메서드 만들기

  • 2.1 절 주의 사항에서 이벤트에 실행할 함수 형태의 값을 전달한다라고 살펴봤었다.
  • 따라서, 이벤트를 처리할 때 렌더링을 하는 동시에 함수를 생성해서 전달했지만, 함수를 미리 정의하여 전달하는 방법이 있다.
    * 미리 정의하여 전달하면 가독성도 좋아질 것 같다.
//EventPractice.js
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 (
      <div>
        <h1>이벤트 연습</h1>
        <input
          type="text"
          name="message"
          placeholder="입력하세요"
          value={this.state.message}
          onChange={this.handleChange}
        />
        <button onClick={this.handleClick}>확인</button>
      </div>
    );
  }
}
  • 위의 코드 처럼 함수가 호출될 때 this는 호출부에 따라 결정되므로, 클래스의 임의 메서드가 특정HTML 요소의 이벤트로 등록되는 과정에서 메서드와 this의 관계가 끊어진다.
  • 이를 해결하기 위해서, 임의 메서드가 이벤트로 등록되어도 this를 컴포넌트 자신으로 제대로 가르키기 위해서 this와 바인딩(binding)해야 한다.
    * 바인딩 하지 않으면 this가 undefined를 가르킨다.

1.2.5 Property Initializer Syntax를 사용한 메서드

  • 메서드 바인딩생성자 메서드에서 하는 것이 일반적이지만, 솔직히 너무 불편하다.😂
    왜냐하면 새로운 메서드를 만들면 생성자도 수정해야 하니까..??
  • 그래서 나온 방법이 있다❗❗ 바로 Babeltransform-class-properties 문법을 사용해서 화살표 함수 형태로 메서드를 정의하는 방법이다.
  • 2.2.4 절 코드를 아래 코드로 변환할 수 있다.
//EventPractice.js
class EventPractice extends Component {
  state = {
    message: "",
  };

  handleChange = (e) => {
    this.setState({
      message: e.target.value,
    });
  }

  handleClick = () => {
    alert(this.state.message);
    this.setState({
      message: "",
    });
  }

  render() {
    return (
      (...)
    );
  }
}
  • 확실히 코드가 간결해졌다. 특히 생성자바인딩 하는 과정이 없고 화살표 함수 형태로 더 깔끔하게 코드를 작성할 수 있다.

1.2.6 input 여러개 다루기

  • 앞서서 input 값을 state에 넣는 방법을 해봤는데, input이 여러개 일 경우는 event 객체를 사용하면 된다.
  • 즉, e.target.name을 사용하면, onChange 이벤트 핸들러에서 e.target.name은 해당 input의 name을 가르키게 된다.
  • 아래의 코드는 위의 코드와는 조금 다르게 구성되어 있다.
    render 함수에서 name 값이 username인 input을 렌더링 했고, state 쪽에도 username을 추가했다.
    추가적으로, handleChange 부분도 변경된 코드가 있다.
//EventPractice
class EventPractice extends Component {
  state = {
    username: '',
    message: ''
  };

  handleChange = (e) => {
    this.setState({
      [e.target.name]: e.target.value,
    });
  }

  handleClick = () => {
    alert(this.state.username + ': ' + this.state.message);
    this.setState({
      username: '',
      message: ''
    });
  }

  render() {
    return (
      <div>
        <h1>이벤트 연습</h1>
        <input
          type="text"
          name="username"
          placeholder="사용자명"
          value={this.state.username}
          onChange={this.handleChange}
        />
        <input
          type="text"
          name="message"
          placeholder="입력하세요"
          value={this.state.message}
          onChange={this.handleChange}
        />
        <button onClick={this.handleClick}>확인</button>
      </div>
    );
  }
}
  • 위의 코드에서 handleChange 함수는 객체 안에서 key를 [ ]로 감싸면 그 안에 넣은 레퍼런스가 가르키는 실제 값이 key로 사용된다.

1.2.7 onKeyPress 이벤트 핸들링

  • onKeyPress 이벤트는 특정 키를 눌렀을 때 발생하는 이벤트 처리 방법이다.
  • 아래의 코드는 comment input에서 Enter를 눌렀을 때 handleClick 메서드를 호출하는 코드이다.
//EventPractice
handleKeyPress = (e) => {
  if(e.key === 'Enter') {
    this.handleClick();
  }
}
  • Enter 키가 인식되면 handleClick 함수를 호출하고, input 요소onKeyPress={this.handleKeyPress}를 추가하면 정상적으로 작동된다.

리액트에서 이벤트 핸들링 하는게 이미 HTML을 한번 맛봐서 그런지 조금? 덜 햇갈린다.
그래도 반복적으로 복습하는거 게으르게 하지말자.❗❗

end

profile
Believe you can & you're half way there 🙏

0개의 댓글