IT

[영어로 배우는 React] 6. 이벤트 핸들링

생각파워 2022. 4. 12. 18:32

공식사이트 : https://reactjs.org/docs/handling-events.html 

 

이번 장에서는 이벤트를 다루는 부분에 대해 알아보겠습니다.

 

리액트 앨리먼트가 이번트를 다루는 방법은 DOM이 이벤트를 다루는 방법과 매우 유사합니다. 아래 몇가지 문법만 빼고요.

  • 리액트 이벤트의 이름은 카멜케이스를 사용합니다.
  • JSX에서 이벤트 핸들러를 함수로 전달할 수 있습니다. 

예를들면 html문법은 아래와 같습니다. 

<button onclick="activateLasers()">
  Activate Lasers
</button>

이와 약간 다르게 리액트는 아래와 같이 사용합니다. 

<button onClick={activateLasers}>
	Activate Lasers
</button>

 

또하나 다른점은 기본작동방식을 막기위해 false를 리턴할 수 없다는 점입니다. 기본작동방식을 막기위해서는 반드시 preventDefault함수를 명시적으로 호출해야 합니다. 

예를 보겠습니다. html에서 폼을 송신하는 작동을 막기위해서는 아래와 같이 사용합니다. 

<form onsubmit="console.log('You clicked submit.'); return false">
  <button type="submit">Submit</button>
</form>

return false를 이용해 더이상의 진행을 막아버리는거죠.

리액트는 preventDefault()함수를 실행해서 처리를 합니다. 

function Form() {
  function handleSubmit(e) {
    e.preventDefault();   
    console.log('You clicked submit.');
  }

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

이렇게요. 두 예제 모두 submit이 실행되지 않습니다. 

여기에서 e는 모조 이벤트입니다. 리액트는 이런 모조 이벤트를 W3C 스펙에 따라서 정의합니다. 그래서 브라우저 호환성에 대해 신경쓰지 않아도 됩니다. 다만 기본 이벤트와 완전히 같이 동작하지는 않습니다. 더 궁금한 점은 SyntheticEvent <= 여기 들어가서 확인해 보세요.

 

리액트를 사용할 때 DOM 앨리먼트에 리스너를 추가하기 위해서 addEventListener를 호출할 필요는 없습니다. 대신에 앨리먼트가 최초로 랜더링될때 기본 리스너를 제공합니다. 

 

컴포넌트를 ES6 클래스 방식으로 정의할 때, 이벤트 핸들러에 대한 공통적인 패턴은 클래스에 메소드로 두는것입니다. 

아래는 유저가 온-오프를 변경하는 버튼을 랜더링하는 Toggle 컴포넌트 입니다. 

class Toggle extends React.Component {
  constructor(props) {
    super(props);
    this.state = {isToggleOn: true};

    // This binding is necessary to make `this` work in the callback
    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>
    );
  }
}

위 예에서는 this.handleClick = this.handleClick.bind(this); 구문을 주의깊게 살펴야 합니다. 자바스크립트에서 클래스 메소드는 자동으로 바운드 되지 않습니다. 만약 이 구문을 써서 handleClick() 메소드에 this를 바운드 시키지 않았다면, 함수를 호출할 때 this는 undefined 값이 되어 handleClick() 메소드를 호출할 수 없을것입니다. 

이것은 리액트 스팩의 작동방식이 아닙니다. 이것은 자바스크립트 함수의 작동방식입니다. 일반적으로 onClick={this.handleClick}과 같이 메소드에 ()(괄호) 없이 참조를 하려한다면, 메소드를 바인딩해야합니다. 

 

만약 바인딩 호출이 귀찮다면, 두가지 방법으로 처리할 수 있습니다. 

첫번째 방법은 클래스 필드 문법입니다. 아래를 잠시 보시죠.

class LoggingButton extends React.Component {
  // This syntax ensures `this` is bound within handleClick.
  // Warning: this is *experimental* syntax.  
  handleClick = () => {    console.log('this is:', this);  }
  
  render() {
    return (
      <button onClick={this.handleClick}>
        Click me
      </button>
    );
  }
}

여기서  handleClick은 클래스의 필드로 정의되었습니다. 이렇게 하면 리스너 내에서 this를 찾을 수 있습니다. 

 

두번째 방법은 화살표 함수 문법을 쓰는것입니다. 

class LoggingButton extends React.Component {
  handleClick() {
    console.log('this is:', this);
  }

  render() {
    // This syntax ensures `this` is bound within handleClick    
    return (      
    	<button onClick={() => this.handleClick()}>        
        	Click me
      	</button>
    );
  }
}

위와 같이 onClick이번트에 리스너를 설정할 때, onClick={() => this.handleClick()} 이렇게 화살표 함수 문법을 사용하면 됩니다. 

 

이벤트로 인자 전달

이벤트에 파라미터를 전달하기 위해서는 아래와 같이 사용합니다.

<button onClick={(e) => this.deleteRow(id, e)}>Delete Row</button>
<button onClick={this.deleteRow.bind(this, id)}>Delete Row</button>

위의 두줄은 같습니다. 화살표 함수와 프로토타입 바인딩 방법을 각각 사용했습니다.

양쪽케이스에서 e는 리액트 이벤트가 두번째 인자로 전달된다는 것을 나타냅니다. 화살표 함수에서는 그것이 명시적으로 전달되었지만, 바인드에서는 자동(묵시적)으로 전달됩니다. 

 

 

 

 

 

반응형