평소와 같이 개발을 하다가
Uncaught TypeError: Cannot read properties of undefined (reading 'setState') ....
이런 에러를 만나게 되었다..?
undefined의 property를 읽을 수 없다는 거 같은데...
오류가 나는 코드를 보니 this.setState({ … }); 처리하는 부분이 있었고, 이 부분에서 this가 컴포넌트를 가르키고 있지 않는 것을 확인할 수 있었다
this.setState({…}) 를 할 때 this 가 컴포넌트를 가르키고 있지 않았던 것
아래 코드 부분입니다 !
위의 코드처럼 객체의 메서드로 일반 함수를 만들어 this를 찍어서 사용하면 그 객체(=getMainButtons)를 가르키게 된다.
일반 함수 형태로 선언되어 있는 getMainButtons()
를 화살표 함수 형태로 만들어주면 된다.
가려져 있지만..
getMainButtons() { … } -> getMainButtons: () => { … }
// 이렇게 수정하면 해결이 됩니다.
this
에 대해서 어렴풋이 알고는 있었지만 확실히 알아보기 위해서 예시를 만들어서 테스트 해보았습니다.
이 부분을 알아보려면 켄텍스트
라는 개념을 알아야 합니다.
함수가 호출될 때 생성되는 컨텍스트.
this
는 그 객체를 가르키고, 일반 함수로 호출되면 전역 객체를 가리키거나 undefined가 됨./* ----------- 객체의 메서드로 호출되는 예시 --------- */
const person = {
name: 'Han0',
greet: function() {
console.log(`Hello, my name is ${this.name}`);
}
};
// 메서드로 호출
person.greet(); // 출력: Hello, my name is Han0
/* ----------- 객체의 메서드로 호출되는 예시 --------- */
this.name = '한영'
const person = {
name: 'YoonHan0',
greet: () => {
console.log(`Hello, my name is ${this.name}`);
}
};
// 메서드로 호출
person.greet(); // 출력: Hello, my name is 한영
아래에는 일반 함수, 화살표 함수를 비교하기 위해 만들어본 예시입니다 !
import React, { Component } from 'react';
class MyComponent extends Component {
constructor(props) {
super(props);
// 일반 함수 바인딩
this.handleIncrement = this.handleIncrement.bind(this);
/* bind 하지 않으면
Uncaught TypeError: Cannot read properties of undefined (reading 'setState') .... 에러 발생
*/
}
state = {
count: 0,
}
// 일반 함수
// 일반 함수는 호출되는 컨텍스트에 따라 this가 결정됨
handleIncrement() {
// 여기서 this는 undefined가 될 수 있습니다.
console.log(this); // undefined (strict mode에서)
this.setState({ count: this.state.count + 1 });
}
// 화살표 함수
// 화살표 함수는 자신이 정의된 컨텍스트의 this를 그대로 사용
handleDecrement = () => {
// 여기서 this는 MyComponent 인스턴스를 가리킵니다.
console.log(this); // MyComponent { ... }
this.setState({ count: this.state.count - 1 });
};
// 위의 일반 함수, 화살표 함수를 테스트하는 함수
testFunc = () => {
this.name = '한영';
const person = {
name: 'Han0',
greet: function () {
console.log(`Hello, my name is ${this.name}`);
}
/*
greet: () => {
console.log(`Hello, my name is ${this.name}`);
}
*/
};
person.greet();
}
render() {
return (
<div>
<h1>Count: {this.state.count}</h1>
<button onClick={this.handleIncrement}>Increment</button>
<button onClick={this.handleDecrement}>Decrement</button>
<button onClick={this.testFunc}>HELLO</button>
</div>
);
}
}
export default MyComponent;
이미지 출처
https://velog.io/@rlacksals96/CS-Javascript-This