Dom Element 에서 이벤트는 합성 이벤트 이다.
- form 의 경우
preventDefault()
를 명시적으로 호출 해야한다 - 브라우저 고유의 event 와 정확히 동일하게 동작하지는 않는다. 하지만 이가 브라우저의 호환성을 맞춰준다.
Class Component 를 사용할 때의 this
- 일반적인 이벤트 핸들링 패턴은, 핸들러를 메서드로 만드는 것이다. 하지만 이때 javascript 의 바인딩 문제를 해결 해 주어야한다.
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
a: 0
};
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
console.log(this.state.a);
}
render() {
return (
<div>
<h1>App</h1>
<button onClick={this.handleClick}>Click</button>
</div>
);
}
}
export default App;
- 위와 같이 onClick 이벤트에 바로 함수를 넣으면, 메서드를 참조하게 된다. 이때 생성자 함수에서 처럼 함수를 바인딩 해주지 않으면 참조하는 값이
undefined
가 된다.
왜 이럴까? javascript 의 동작방식에 그 해답이 있다. javascript 에서 this는 반드시 실행시점에 결정된다는 점을 유의해야한다. 그렇다면 render()함수가 호출되고 나서, DOM 에서 this.handleClick 은 window 객체를 참조하게 된다(실행 context가 window가 됨)
- 이를 해결하기 위해서는 위 코드와 같이 직접
bind()
함수를 선언하는 방법 or arrow function 을 사용해서 자동으로 바인딩 시키는 방법이 있다(class field 문법). 혹은 콜백 자체에 arrow function을 사용하는 방법이 있습니다.
arrow function 은 항상 상위 스코프의
this
를 바인딩하는데, 이를Lexical this
라 합니다.
React에서 지원하는 class field 문법 을 사용한 예시 (arrow function)
Class Field 문법이란 ? 말그대로 class 에 사용되는 새로운 문법입니다. React Component 를 만들때 반드시 constructor()에 super() 와 state를 정의해주고, 모든 메서드들을 바인딩 해주었습니다. 이 동작들을 간소화할 수 있게 해주는 문법으로써, 핵심적으로 constructor() 를 정의하지 않습니다. 모든 메서들은 arrow function 으로 정의하고, 이는 자동으로 바인딩됩니다.
constructor(), this 가 사라진 형태
class App extends React.Component {
state = {
a:10,
name:'kong'
}
handleClick = () => {
console.log(this);
};
render() {
return (
<div>
<h1>App</h1>
<button onClick={this.handleClick}>Click</button>
</div>
);
}
}
export default App;
callback 에 arrow function 사용 예시 (권장되지 않음 : 콜백 성능 이슈)
이 방식의 문제점은 App 컴포넌트가 재렌더링 될때마다 새로운 callback을 생성한다는 점입니다. 대부분의 경우에 문제가 없지만 만약 이 콜백함수가 자식 컴포넌트의 props로 전달되고있다면, 콜백이 생성될 때마다 자식 컴포넌트도 재렌더링 됩니다. 이러한 문제 때문에 class field 문법을 사용하거나, 생성자 안에서 바인딩 해주는 방식이 권장됩니다.
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
a: 0
};
}
handleClick() {
console.log(this);
}
render() {
return (
<div>
<h1>App</h1>
<button onClick={() => this.handleClick()}>Click</button>
</div>
);
}
}
export default App;
callback에서 binding 하기
class App extends React.Component {
constructor(props){
super(props);
}
handleClick(pram){
console.log(this,pram);
};
render() {
return (
<div>
<h1>App</h1>
<button onClick={this.handleClick.bind(this,3)}>Click</button>
</div>
);
}
}
export default App;
반응형
'Archive' 카테고리의 다른 글
React Custom Hook return Array vs Object 차이 (0) | 2022.06.07 |
---|---|
React 조건부 렌더링(falsy에서 유의하자) (0) | 2022.06.06 |
AWS serverless (API gateway + lambda) (0) | 2022.06.04 |
AWS EB 사용하기 (0) | 2022.06.03 |
React Query 도입하기 (0) | 2022.05.19 |