event
class component에서의 Event 처리 방법에 대해서 살펴본다.
Event 처리
이벤트를 처리하기 위해서는 함수가 필요하며, 클래스 컴포넌트에 함수를 배치하는 방법은 여러 가지가 존재한다.
Function.prototype.call() / .apply()
Function.prototype.bind()
Babel transform-class-properties 문법
Arrow function
화살표 함수로 이벤트를 처리할 경우 다음과 같이 작성한다. 다음 JSX 코드는 버튼을 클릭할 경우 알림창이 출력되는 코드이다.
<button onClick={()=>{window.alert('click event')}}>click</button>
추가 메소드를 구현하지 않아도 되므로 인라인으로 간편하게 처리할 수 있으나, 코드가 길어지면 가독성이 떨어지므로 간단한 코드 작성 시 유리하다. Arrow function 내에서 this라는 키워드를 사용할 경우 해당 컴포넌트 객체에 접근할 수 있다.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>React CDN Example</title>
</head>
<body>
<div id="app"></div>
<!-- 개발용 CDN -->
<script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<!-- 배포용 CDN -->
<!-- <script crossorigin src="https://unpkg.com/react@18/umd/react.production.min.js"></script> -->
<!-- <script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script> -->
<!-- 바벨 CDN(using JSX) -->
<script src=" https://unpkg.com/@babel/standalone/babel.min.js"></script>
<script type="text/babel">
class MainComponent extends React.Component {
render(){
return (
<>
<button onClick={()=>{ alert('click event') }}>click</button>
</>
);
}
}
const app = ReactDOM.createRoot(document.querySelector("#app"));
app.render(
<MainComponent/>
);
</script>
</body>
</html>
클래스 메소드 지정
React Component Class 내부에 메소드를 만들고 이를 지정하여 호출할 수 있다.
class MainComponent extends React.Component {
clickEventProcessor(){
window.alert('click event');
}
render(){
return (
<>
<button onClick={this.clickEventProcessor}>click</button>
</>
);
}
}
클래스 메소드로 이벤트를 처리할 경우 문제점
위와 같이 클래스에 생성한 메소드로 이벤트를 처리할 경우 react component에 접근할 수 없다. this가 undefined로 출력되며, state, props 등 컴포넌트의 다른 구성요소에 접근할 수 없어 컴포넌트와 상관 없는 작업만 처리할 수 있다.
class MainComponent extends React.Component {
clickEventProcessor(){
console.log(this);
}
render(){
return (
<>
<button onClick={this.clickEventProcessor}>click</button>
</>
);
}
}
Function.prototype.call() / .apply()
Function에서 제공하는 call 함수와 apply 함수를 이용하면 this를 설정하며 함수 호출이 가능하다. 이를 이용하여 다음과 같이 이벤트를 설정할 수 있다.
class MainComponent extends React.Component {
clickEventProcessor(){
console.log(this);
window.alert('click event');
}
render(){
return (
<>
<button onClick={()=>this.clickEventProcessor.call(this)}>click</button>
<button onClick={()=>this.clickEventProcessor.apply(this)}>click</button>
</>
);
}
}
Function.prototype.call()과 Function.prototype.apply()는 동일한 기능을 수행하지만 다음 차이가 있다.
Function.prorotype.apply()는 인수를 배열로 전달한다.
Function.prototype.call()은 인수를 그대로 전달한다.
Function.prototype.bind()
Function.prototype.bind()를 사용하여 이벤트 처리 함수를 재할당 하여 사용하는 방법이 있다.
class MainComponent extends React.Component {
constructor(){
super();
this.clickEventProcessor = this.clickEventProcessor.bind(this);
}
clickEventProcessor(){
console.log(this);
window.alert('click event');
}
render(){
return (
<>
<button onClick={this.clickEventProcessor}>click</button>
</>
);
}
}
핵심 코드는 생성자(constructor)에 있는 bind 코드이다.
this.clickEventProcessor = this.clickEventProcessor.bind(this);
clickEventProcessor에 this를 설정하여 재할당 한 뒤 사용하면 정상적으로 이벤트 함수에서 this가 MainComponent로 출력된다.
Babel class-transform-properties
Babel에서 제공하는 변환 코드를 사용하여 Function.prototype.bind() 대신 사용할 수 있다. 다음과 같은 형태로 이벤트 처리 메소드를 작성한다.
class MainComponent extends React.Component {
constructor(){
super();
}
clickEventProcessor = ()=>{
console.log(this);
window.alert('click event');
}
render(){
return (
<>
<button onClick={this.clickEventProcessor}>click</button>
</>
);
}
}
주의사항은 처리 함수는 반드시 화살표 함수로 작성해야 하며, 다음과 같이 작성하면 안된다는 것이다.
clickEventProcessor = function(){
console.log(this);
window.alert('click event');
}
실행하면 정상적으로 출력되는 것을 확인할 수 있다.
결론
이벤트 처리는 다음과 같은 방법으로 한다.
지원하는 이벤트의 종류는 다음과 같다.