React element의 이벤트를 처리하는 방식은 DOM element의 이벤트를 처리하는 방식과 매우 유사하나, 몇 가지 문법 차이가 있다.
예시로 차이를 확인하자.
html
<button onclick="activateLasers()">
Activate Lasers
</button>
jsx
<button onClick={activateLasers}>
Activate Lasers
</button>
또 다른 차이점으로, React에서는 false를 반환해도 default 동작을 방지할 수 없다. 반드시 preventDefault를 명시적으로 호출해야 한다.
html
<form onsubmit="console.log('You clicked submit.'); return false">
<button type="submit">Submit</submit>
</form>
jsx
function Form() {
function handleSubmit(e) {
e.preventDefault();
console.log('You clicked submit.');
}
return (
<form onSubmit={handleSubmit}>
<button type="submit">Submit</buttom>
</form>
);
}
React를 사용할 때 DOM element가 생성된 후, listener를 추가하기 위해 addEventListener를 호출할 필요가 없다. 대신, element가 처음 렌더링될 때 listener를 제공하면 된다.
클래스를 사용하여 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')
);
JavaScript에서 클래스 메서드는 기본적으로 바인딩되어 있지 않다. this.handleClick을 바인딩하지 않고, onClick에 전달하였다면, 함수가 실제로 호출될 때 this는 undefined가 된다.
일반적으로 onClick={this.handleClick}과 같이 뒤에 ()를 사용하지 않고 메서드를 참조할 경우, 해당 메서드를 바인딩 해야 한다.
생성자 안에 bind 호출을 하는 방법 이외에도, public 클래스 필드 syntax를 사용하는 방법이 있다. 클래스 필드를 사용하여 콜백을 바인딩한다.
class LoggingButton extends React.Component {
handleClick = () => {
console.log('this is:', this);
}
render() {
return (
<button onClick={this.handleClick}>
Click me
</button>
);
}
}
반복문 내부에서는 이벤트 핸들러에 추가적인 매개변수를 전달하는 것이 일반적이다.
예를 들어, id가 행의 ID일 경우 다음 두 코드는 동일한 동작을 한다. 각각 화살표 함수와 Function.prototype.bind를 사용한다.
<button onClick={(e) => this.deleteRow(id, e)}>Delete Row</button>
<button onClick={this.deleteRow.bind(this, id)}>Delete Row</button>
두 경우 모두 React 이벤트를 나타내는 e 인자가 ID 뒤에 두 번째 인자로 전달된다. 화살표 함수를 사용하면 명시적으로 인자를 전달해야 하지만 bind를 사용할 경우 추가 인자가 자동으로 전달된다.