• React Element에서 이벤트 처리하는 방식은 DOM Element 에서 이벤트를 처리하는 방식과 매우 유사합니다. 몇 가지 문법 차이는 다음과 같습니다.

    • React의 이벤트는 소문자 대신 캐멀 케이스(camelCase)를 사용합니다.
    • JSX를 사용하여 문자열이 아닌 함수로 이벤트 핸들러를 전달합니다.
    // HTML
    <button onclick="activateLasers()">
      Activate Lasers
    </button>
    
    // JSX
    <button onClick={activateLasers}>
      Activate Lasers
    </button>
    
  • 또 다른 차이점으로, React에서는 false를 반환해도 기본 동작을 방지할 수 없습니다.

    반드시 preventDefault()를 명시적으로 호출해야 합니다. 예를 들어, 일반 HTML에서 폼을 제출할 때 가지고 있느 기본 동작을 방지하기 위해 다음과 같은 코드를 작성할 수 있습니다.

    // HTML
    <form onsubmit="console.log('You clicked submit.'); return false">
      <button type="submit">Submit</button>
    </form>
    
    // JSX
    function Form() {
      function handleSubmit(e) { // e -> 합성 이벤트
        e.preventDefault();
        console.log('You clicked submit.');
      }
    
      return (
        <form onSubmit={handleSubmit}>
          <button type="submit">Submit</button>
        </form>
      );
    }
    

    React를 사용할 때 DOM Element가 생성된 후 리스너를 추가하기 위해 addEventListener를 호출할 필요가 없습니다. 대신, Element가 처음 렌더링될 때 리스너를 제공하면 됩니다.

    ES6 클래스를 사용하여 Component를 정의할 때, 일반적인 패턴은 이벤트 핸들러를 클래스의 메서드로 만드는 것입니다. 예를 들어, 다음 Toggle Component는 사용자가 “ON” 과 “OFF” 상태를 토글 할 수 있는 버튼을 렌더링합니다.

    class Toggle extends React.Component {
      constructor(props) {
        super(props);
        this.state = {isToggleOn: true};
    
        *// 콜백에서 `this`가 작동하려면 아래와 같이 바인딩 해주어야 합니다.
    		// (생성자 안에서 바인딩)*
        this.handleClick = this.handleClick.bind(this);
      }
    
      handleClick() {
        this.setState(prevState => ({
          isToggleOn: !prevState.isToggleOn
        }));
      }
    
      render() {
        return (
          <button onClick={this.handleClick}>
            {this.state.isToggleOn ? 'ON' : 'OFF'}
          </button>
        );
      }
    }
    
    ReactDOM.render(
      <Toggle />,
      document.getElementById('root')
    );
    
  • JSX 콜백 안에서 this의 의미에 대해 주의해야 합니다. JavaScript에서 클래스 메서드는 기본적으로 바인딩되어 있지 않습니다. this.handleClick을 바인딩하지 않고 onClick에 전달하였다면, 함수가 실제 호출될 때 this는 undefined가 됩니다.

    이는 React 만의 특수한 동작이 아니며, JavaScript에서 함수가 작동하는 방식의 일부입니다.

    일반적으로 onClick={this.handleClick} 과 같이 뒤에 () 를 사용하지 않고 메서드를 참조할 경우, 해당 메서드를 바인딩 해야 합니다.

    • 생정자 안에서 bind(객체) 함수를 사용하거나
    • 클래스 필드에서 Arrow function () ⇒ {} 을 사용하여 객체를 바인딩 해준다.

    ⚠️ 피해야 하는 이벤트 핸들러 함수 선언 방식

    class LoggingButton extends React.Component {
      handleClick() {
        console.log('this is:', this);
      }
    
      render() {
        // 이 문법은 `this`가 handleClick 내에서 바인딩되도록 합니다.
        return (
          <button onClick={() => this.handleClick()}>
            Click me
          </button>
        );
      }
    }
    

    이 문법읜 문제점은 LoggingButton 이 렌더링될 때마다 다른 콜백이 생성된다는 것입니다.

    (즉, 함수를 this.handleClick 처럼 참조하는 것이 아니라 선언되어 렌더링될 때마다 함수가 생성된다.)

    대부분의 경우 문제가 되지 않으나, 콜백이 하위 컴포넌트에 props로서 전달된다면 그 컴포넌트들은 추가로 다시 렌더링을 수행할 수도 있습니다.

    이러한 종류의 성능 문제를 피하고자, 생성자 안에서 바인딩하거나 클래스 필드 문법을 사용하는 것을 권장합니다.