합성이벤트 e
SyntheticEvent
- SyntheticEvent 객체는 모든 브라우저에서 이벤트를 동일하게 처리하기 위한 래퍼객체이다.
- React에서 엘리먼트의 이벤트를 처리하기 위해 제공하는 이벤트리스너의 인자(e)가 매번 초기화 된다. (풀링이라는 개념)
- stopPropagation() 와 preventDefault()를 포함해서 인터페이스는 브라우저의 고유 이벤트와 같다.
아래 HTML 코드를 보면
1. 이벤트를 소문자로 적음(onclick)
2. 문자열이벤트
인것을 볼수있다.
<button onclick="activateLasers()">
Activate Lasers
</button>
리액트에서는 아래처럼 작성할수있다
1. 우선 이벤트를 camelCase로 적었고
2. 이벤트를 함수로 전달했다. (activateLasers함수는 다른데 선언되어 있음)
<button onClick={activateLasers}>
Activate Lasers
</button>
일반 HTML에서는 새 페이지를 여는 링크의 기본동작을 방지하기위해 이벤트에서 False를 return 해줄수있다.
<a href="#" onclick="console.log('The link was clicked.'); return false">
Click me
</a>
React에서는 이벤트핸들러가 false를 반환해도 기본동작을 방지할수 없다. 만약 방지하려고한다면 인자로 합성이벤트e를 받아 e.preventDefault()를 명시적으로 호출해야 한다.
function ActionLink() {
function handleClick(e) {
e.preventDefault();
console.log('The link was clicked.');
}
return (
<a href="#" onClick={handleClick}>
Click me
</a>
);
}
React에서는 DOM엘리먼트가 생성된 후 리스너를 추가하기위해 addEventListener를 호출할 필요가 없다. 대신 엘리먼트가 처음 렌더링될때 리스터를 제공하면 된다.
아래의 클래스컴포넌트를 보면 이벤트핸들러를 클래스의 메서드로 만들어서, 컴포넌트 내에서 사용할수있다.
class Toggle extends React.Component {
constructor(props) {
super(props);
this.state = {isToggleOn: true};
// 콜백에서 `this`가 작동하려면 아래와 같이 바인딩 해주어야 합니다.
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState(state => ({
isToggleOn: !state.isToggleOn
}));
}
render() {
return (
<button onClick={this.handleClick}>
{this.state.isToggleOn ? 'ON' : 'OFF'}
</button>
);
}
}
ReactDOM.render(
<Toggle />,
document.getElementById('root')
);
주의해야 할것
JS에서 클래스 메서드는 기본적으로 바인딩되어있지 않기때문에 this.handleClick을 바인딩하지않고 호출하면, this는 undefined가 된다. 그래서 바인딩 해주고 사용해야 한다.
constructor에서 바인딩하는 방법 말고 화살표 함수를 사용하게 되면 화살표 함수는 외부스코프의 this를 자동으로 binding 하기때문에 화살표함수로 작성한 이벤트핸들러에서 this를 사용해 접근이 가능하다.
class LoggingButton extends React.Component {
handleClick() {
console.log('this is:', this);
}
render() {
// 이 문법은 `this`가 handleClick 내에서 바인딩되도록 합니다.
return (
<button onClick={() => this.handleClick()}>
Click me
</button>
);
}
}
하지만 이러한 방식은 LoggingButton이 렌더링 될때마다 다른 콜백이 생성된다.
위 내용이 더 궁금하다면 컴포넌트에 함수 전달하기를 읽어보세요
예를 들어 인자로 엘리먼트가 가진 data인 id를 넣어주려고 할때,
<button onClick={(e) => this.deleteRow(id, e)}>Delete Row</button>
명시적으로 e를 전달해줘야 함
<button onClick={this.deleteRow.bind(this, id)}>Delete Row</button>
bind함수를 사용하는 경우 e인자가 자동으로 전달됨
참고