발단
조금 예전 리액트 강의들을 따라하다보면 함수형 컴포넌트보다는 클래스형 컴포넌트를 사용한 것들이 많고,
클래스형 컴포넌트에서 state의 초깃값 정의 부분도 constructor() 생성자 함수 없이 그냥 곧바로 정의해주는 경우가 많았다.
class Header extends Component {
state = {
buttonDisplay: "none"
};
에러 메시지
이는 eslint 오류를 발생시키는데,
바로, class 컴포넌트의 state의 초깃값 설정 부분은 constructor() 생성자 함수 안에 들어가야한다는 것이다
State initialization should be in a constructor eslint(react/state-in-constructor)
해결
state 초깃값 정의 부분을 constructor() 생성자 함수 안에 넣어주면 간단하게 해결 가능하다.
class Header extends Component {
constructor(props) {
super(props);
this.state = {
buttonDisplay: "none",
};
}
단, constructor() 생성자 함수를 정의할 때 주의할 점은
(1) 파라미터로 props를 받아주어야 하고
(2) super(props);를 호출해주어야 하며
(3) state 앞에 this를 붙여주어야 한다
Tip. class 컴포넌트 관련 개념
class
: 객체를 생성하기 위해 ES6에서 추가된 문법 (리액트 문법 X)
class 선언 방법
class Header extends Component {
...
}
(1) class 뒤에 클래스명을 입력 해주고
(2) 객체를 의미하는 {} 안에 값을 넣습니다.
(3) extends: 다른 클래스의 자식 클래스를 생성하기 위해 사용
constructor() 생성자 함수
: class 객체를 만드는 데 필요한 값에 대해서 선언해 주고 초기화해주는 특수 메서드.
constructor(props) {
super(props);
this.state = {
buttonDisplay: "none",
}
}
(1) 클래스 안에 한 개만 존재할 수 있다
(2) super() : 부모 클래스(React.Component)의 constructor() 호출 가능, 항상 생성자의 첫줄에 와야 한다
this
: 클래스 컴포넌트에 선언한 놈들을 참조하기 위해 사용
- state (+setState)
- props
- refs
- 컴포넌트 메서드 ⇒ 이벤트 핸들링시 예외 발생
- 생명주기 매서드
class BoardDetail extends Component {
constructor(props) {
this.state = { board: [], } // 클래스 컴포넌트 BoardDetail의 state
}
componentDidMount() {
if (this.props.location.query !== undefined) { this.getDetail(); }
// 클래스 컴포넌트 BoardDetail의 props
// 클래스 컴포넌트 BoardDetail의 getDetail() 커스텀메서드 호출
else { window.location.href = "/"; }
}
deleteBoard = (_id) => {
...
}
render() {
return (
<Button onClick={this.deleteBoard.bind(nulll, this.props.location.query._id)}>
)
}
this.state = BoardDetail.state / this.props = BoardDetail.props / this.getDeatil() = BoardDetail.getDetail()
이런 식으로 인스턴스에 .을 붙여 호출시 -> 정상적으로 클래스 컴포넌트에 바인딩되어 참조 가능
But, 컴포넌트에서 선언한 메서드를 -> JSX 이벤트 핸들러의 콜백 함수로 를 전달할 때 문제 발생
= 메서드를 다른 변수에 옮겨 호출시 -> TypeError 발생
deleteBoard = (_id) => {
// axios의 메서드들(post(), then(), catch())을 -> deleteBoard 변수로 옮긴 후
axios
.post()
.then()
.catch()
}
<Button onClick={this.deleteBoard}> // deleteBoard() 변수로 호출
// 원래 바인딩되어 있던 클래스 BoardDetail을 잃어버리고 -> 전역 객체인 window/global에 바인딩되어 참조 불가능해짐
해결 방법
[1] bind()
: 어떤 함수의 this를 명시하는 역할을 하는 Function 객체의 메서드
<Button onClick={ this.deleteBoard.bind(nulll, this.props.location.query._id)}>
bind() 호출시 -> 인자로 받은 객체를 this로 하는 새로운 함수를 리턴
- 이벤트 핸들러로 bind()를 호출한 메서드 this.deleteBoard.bind()를 넘긴다
- constructor()에 작성한다
[2] 화살표 함수
: 화살표 함수는 다른 함수와 달리 따로 this를 가지고 있지 않고, 항상 상위 스코프의 this에 바인딩한다(lexical this)
render() {
return (
<Button onClick={ () => this.deleteBoard() } >
)
}
상위 스코프인 render() 메서드의 this인 클래스 컴포넌트 BoardDetail에 바인딩
참조