React 엘리먼트에서 이벤트를 처리하는 방식은 DOM 엘리먼트에서 이벤트를 처리하는 방식과 매우 유사하지만 차이점이 있습니다.
// HTML
<button onclick="activateLasers()">
Activate Lasers
</button>
// React
<button onClick={activateLasers}>
Activate Lasers
</button>
false
를 반환해도 기본 동작을 방지할 수 없다.preventDefault
를 명시적으로 호출해야한다.// HTML
<form onsubmit="console.log('You clicked submit.'); return false">
<button type="submit">Submit</button>
</form>
// React
function Form() {
function handleSubmit(e) {
// e는 합성 이벤트(SyntheticEvent)
e.preventDefault();
console.log('You clicked submit.');
}
return (
<form onSubmit={handleSubmit}>
<button type="submit">Submit</button>
</form>
)
}
예를 들어, 다음 Toggle
컴포넌트는 사용자가 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>
);
}
}
JSX 콜백 안에서 this
의 의미에 대해 주의해야 합니다. JavaScript에서 클래스 메서드는 기본적으로 바인딩되어 있지 않습니다. this.handleClick
을 바인딩하지 않고 onClick
에 전달하면, 함수가 실제 호출될 때 this
는 undefined
가 됩니다.
⇒ JavaScript에서 함수가 동작하는 방식으로 React의 특수한 동작이 아니다.
일반적으로 onClick={this.handleClick}
과 같이 뒤에 ()
를 사용하지 않고 메서드를 참조할 경우, 해당 메서드를 바인딩 해야 합니다.
class LoggingButton extends React.Component {
// 이 문법은 this가 handleClick 내에서 바인딩되도록 한다.
// 주의 : 이 문법은 *실험적인* 문법이다.
handleClick = () => {
console.log('this is:', this);
}
render() {
return (
<button onClick={this.handleClick}>
Click me
</button>
)
}
}
LoggingButton
이 렌더링될 때마다 다른 콜백이 생성⇒ 이러한 종류의 성능 문제를 피하고자, 생성자 안에서 바인딩하거나 클래스 필드 문법을 사용하는 것을 권장
class LoggingButton extends React.Component {
handleClick = () => {
console.log('this is:', this);
}
render() {
return (
// 이 문법은 this가 handleClick 내에서 바인딩되도록 한다.
<button onClick={() => this.handleClick()}>
Click me
</button>
)
}
}
루프 내부에서는 이벤트 핸들러에 추가적인 매개변수를 전달하는 것이 일반적입니다.
예를 들어, id가 행의 ID일 경우 다음 코드가 모두 작동합니다.
// 화살표 함수 사용
<button onClick={(e) => this.deleteRow(id, e)}>
Delete Row
</button>
// Function.prototype.bind 사용
<button onClick={this.deleteRow.bind(this, id)}>
Delete Row
</button>
두 경우 모두 React 이벤트를 나타내는 e
인자가 ID 뒤에 두 번째 인자로 전달됩니다. 화살표 함수를 사용하면 명시적으로 인자를 전달해야 하지만 bind
를 사용할 경우 추가 인자가 자동으로 전달됩니다.