클래스 컴포넌트를 복습하면서 constructor 내부에서 클래스 내부에 선언한 메서드에 대해 bind한 이유를 명확히 이해하지 못해 다시 보게 되었다.
우선, 버튼을 클릭할때마다 isToggleOn값이 변화되며 button의 텍스트가 변경되게 하려는 의도로 작성한 코드는 다음과 같다.
import React from 'react';
import './app.css';
class App extends React.Component {
constructor(props) {
super(props);
this.state = {isToggleOn: true};
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
console.log('handleClick func: ',this);
this.setState(state => ({
isToggleOn: !state.isToggleOn
}));
}
render() {
return (
<button onClick={this.handleClick}>
{this.state.isToggleOn ? 'ON' : 'OFF'}
</button>
);
}
}
constructor(props) {
super(props);
this.state = {isToggleOn: true};
this.handleClick = this.handleClick.bind(this);
}
이 경우 버튼을 클릭하게 되면 우리가 의도했던 대로 this가 App component를 가리키면서 잘 작동한다.
constructor(props) {
super(props);
this.state = {isToggleOn: true};
}
하지만 binding을 하지 않았을 경우에는 handleClick func의 내부의 this는 undefined를 가리키며 잘 작동하지 않는다.
this를 배우면서 어떻게 호출하냐에 따라 this값이 달라진다고 했는데 이 경우에는 버튼을 클릭하면서 함수방식으로 호출하기 때문에 전역 객체인 window를 가리켜야 하지만 strict mode가 적용되어 있어 undefined값이 나오게 된 것
이다.
그래서 이를 해결하려면 bind() 메서드를 사용하여 명시적으로 바인딩을 해주거나 arrow function방식으로 변경
하면 우리가 원했던 this값을 얻을 수 있게 된다.
constructor(props) {
super(props);
this.state = {isToggleOn: true};
// this.handleClick = this.handleClick.bind(this);
}
handleClick = () => {
console.log('handleClick func: ',this);
this.setState(state => ({
isToggleOn: !state.isToggleOn
}));
}
또는
handleClick() {
console.log('handleClick func: ',this);
this.setState(state => ({
isToggleOn: !state.isToggleOn
}));
}
render() {
console.log(this);
return (
<button onClick={() => this.handleClick()}>
{this.state.isToggleOn ? 'ON' : 'OFF'}
</button>
);
}