
ES6 클래스를 사용하여 컴포넌트를 정의할 때, 메서드 내부에서 this 에 접근하면 undefined 가 출력된다.
이는 Javascript 클래스 메서드는 기본적으로 바인딩 되어있지 않아 발생하는 문제이기 때문에, 별도로 바인딩 조치를 하는 작업이 필요하다.
React 공식 문서에서는 this 를 바인딩하는 세 가지 방식을 소개하고있다.
Javascript 클래스 생성자 내부에서 bind 함수를 호출해 바인딩한다.
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>
);
}
}
ReactDOM.render(
<Toggle />,
document.getElementById('root')
);
퍼블릭 클래스 필드 문법을 사용하면 좀 더 간단하게 바인딩할 수 있다. CRA 에서는 이 문법이 기본적으로 사용 설정 되어있다.
class LoggingButton extends React.Component {
// 이 문법은 `this`가 handleClick 내에서 바인딩되도록 합니다.
// 주의: 이 문법은 *실험적인* 문법입니다.
handleClick = () => {
console.log('this is:', this);
}
render() {
return (
<button onClick={this.handleClick}>
Click me
</button>
);
}
}
콜백 함수에 화살표 함수를 사용하여 바인딩 할 수 있다.
다만, 이 방식은 컴포넌트가 렌더링될 때마다 다른 콜백을 생성한다. 하위 컴포넌트에 props로 콜백이 전달될 경우 불필요하게 재렌더링되는 성능 문제를 일으킬 수 있다.
class LoggingButton extends React.Component {
handleClick() {
console.log('this is:', this);
}
render() {
// 이 문법은 `this`가 handleClick 내에서 바인딩되도록 합니다.
return (
<button onClick={() => this.handleClick()}>
Click me
</button>
);
}
}