React 이벤트 처리와 조건부 렌더링

React 이벤트 처리 및 렌더링 가이드

이벤트 처리

React 엘리먼트에서 이벤트를 처리하는 방식은 DOM 엘리먼트에서 이벤트를 처리하는 방식과 매우 유사하지만, React 이벤트는 소문자 대신 카멜케이스를 사용하고, JSX를 사용하여 문자열이 아닌 함수로 이벤트 핸들러를 전달한다는 차이가 있습니다.

HTML의 이벤트 처리 방식
<button onclick="activateLasers()">
  Activate Lasers
</button>
React의 이벤트 처리 방식
<button onClick={activateLasers}>
  Activate Lasers
</button>

또 React에서는 false를 반환해도 기본 동작을 방지할 수 없기 때문에 HTML에서 폼을 제출할 때 사용되는 기본 동작을 방지하기 위해서는 반드시 preventDefault를 명시적으로 호출해 주어야 합니다.

HTML 폼 기본동작 막기
<form onsubmit="console.log('You clicked submit.'); return false">
  <button type="submit">Submit</button>
</form>
React 폼 기본동작 막기
function Form() {
  function handleSubmit(e) {
    e.preventDefault();
    console.log('You clicked submit.');
  }

  return (
    <form onSubmit={handleSubmit}>
      <button type="submit">Submit</button>
    </form>
  );
}

위 코드에서 e는 합성 이벤트를 뜻하는데, React는 W3C 명세에 따라 합성 이벤트를 정의하기 때문에 브라우저 호환성에 대해 걱정할 필요가 없지만, React 이벤트는 브라우저의 고유 이벤트와 정확히 동일하게 동작하지는 않는다고 합니다.

React에서는 DOM 엘리먼트가 생성된 후 리스너를 추가하기 위해 addEventListener를 호출할 필요없이 엘리먼트가 처음 렌더링될 때 리스너를 제공하면 됩니다.

ES6 클래스로 컴포넌트 정의하기
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')
);

ES6 클래스를 사용하여 컴포넌트를 정의할 때, 일반적인 패턴은 이벤트 핸들러를 클래스의 메서드로 만드는 겁니다. 위 코드에서 Toggle 컴포넌트는 사용자가 ONOFF 상태를 토글 할 수 있는 버튼을 렌더링할 수 있습니다.

JSX 콜백 안에서는 this의 의미에 대해 주의할 필요가 있는데, JavaScript에서 클래스 메서드는 기본적으로 바인딩되어 있지 않습니다. 그래서 this.handleClick을 바인딩하지 않고 onClick에 전달하면 함수가 실제 호출될 때 thisundefined를 가리키게 됩니다.

이런 동작은 사실 React 뿐만 아니라 JavaScript에서 함수가 작동하는 방식이라고 할 수 있는데, 일반적으로 onClick={this.handleClick}과 같이 뒤에 괄호()를 사용하지 않고 메서드를 참조하는 경우에는 해당 메서드를 바인딩 해주어야 합니다.

만약 bind를 호출하는 것이 불편하다면, 이를 해결할 수 있는 두 가지 방법이 있는데, 우선 퍼블릭 클래스 필드 문법을 사용하는 경우라면 클래스 필드를 사용하여 콜백을 올바르게 바인딩할 수 있습니다.

이 방식은 실험적인 문법이기 때문에 많이 사용되지는 않지만, Create React App에서는 이 문법이 기본적으로 설정되어 있습니다.

클래스 필드로 콜백 바인딩하기
class LoggingButton extends React.Component {
  // `this`가 handleClick 내에서 바인딩되도록 하는 문법
  handleClick = () => {
    console.log('this is:', this);
  }

  render() {
    return (
      <button onClick={this.handleClick}>
        Click me
      </button>
    );
  }
}

클래스 필드 문법 대신 콜백에 화살표 함수를 사용하는 방법도 있습니다.

화살표 함수로 바인딩하기

답글 남기기