🔎 React 공식문서 자료
React_이벤트 처리하기
React 엘리먼트에서 이벤트를 처리하는 방식은 DOM 엘리먼트에서 이벤트를 처리하는 방식과 매우 유사하다. 몇 가지 문법 차이는 다음과 같다.
카멜 케이스(camelCase)
를 사용한다.⚙️ HTML 코드
<button onclick="activateLasers()">
Activate Lasers
</button>
⚙️ React 코드
<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>
⚙️ 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는 W3 명세에 따라 합성 이벤트를 정의하기 때문에 브라우저 호환성에 대해 걱정할 필요가 없다. React 이벤트는 브라우저 고유 이벤트와 정확히 동일하게 동작하지는 않는다.
React를 사용할 때 DOM 엘리먼트가 생성된 후 리스너를 추가하기 위해 addEventListener
를 호출할 필요가 없다. 대신, 엘리먼트가 처음 렌더링될 때 리스너를 제공하면 된다.
ES6 클래스를 사용하여 컴포넌트를 정의할 깨, 일반적인 패턴은 이벤트 핸들러를 클래스의 메서드로 만드는 것이다. 예를 들어, 다음 Toggle
컴포넌트는 사용자가 ON
과 OFF
상태를 토글할 수 있는 버튼을 렌더링한다.
✨ bind?
bind()
메소드가 호출되면 새로운 함수를 생성this
키워드를 설정하고, 이어지는 인자들은 바인드된 함수의 인수에 제공JSX 콜백 안에서 this
의 의미에 대해 쥐의해야 한다. JavaScript에서 클래스 메서드는 기본적으로 바인딩되어 있지 않다. this.handleClick
을 바인딩하지 않고 onClick
에 전달하였다면, 함수가 실제 호출될 때 this
는 undefined
가 된다.
이는 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>
);
}
}
🔎 퍼블릭 클래스 필드 문법 ❌
class LoggingButton extends React.Component {
handleClick() {
console.log('this is:', this);
}
render() {
// 이 문법은 `this`가 handleClick 내에서 바인딩되도록 합니다.
return (
<button onClick={() => this.handleClick()}>
Click me
</button>
);
}
}
이 문법의 문제점은 LogginButton
이 렌더링될 때마다 다른 콜백이 생성된다. 대부분의 경우 문제가 되지 않으나, 콜백이 하위 컴포넌트에 props로서 전달된다면 그 컴포넌트들은 추가로 다시 렌더링을 수행할 수 도 있다. 이러한 종류의 성능 문제를 피하고자, 생성자 안에서 바인딩하거나 클래스 문법을 사용하는 것을 권장한다.
루프 내부에서는 이벤트 핸들러에 추가적인 매개변수를 전달하는 것이 일반적이다. 예를 들어, id
가 행의 ID일 경우 다음 코드가 모두 작동한다.
// ▶ 두 코드는 서로 동등함!
// ⚙️ 화살표 함수 코드
<button onClick={(e) => this.deleteRow(id, e)}>Delete Row</button>
// ⚙️ Funtion.porototype.bind 코드
<button onClick={this.deleteRow.bind(this, id)}>Delete Row</button>
두 경우 모두 React 이벤트를 나타내는 e
인자가 ID 뒤에 두 번째 인자로 전달된다. 화살표 함수를 사용하면 명시적으로 인자를 전달해야 하지만 bind
를 사용할 경우 추가 인자가 자동으로 전달된다.