몬스터 흰색은 왜 맛있을까
먼저 앞서 요약해서 말하면 props는 부모 컴포넌트가 자식 컴포넌트에게 주는 값이다. 자식 컴포넌트에서는 props를 받아오기만하고, 받아온 props를 직접 수정은 불가능하다.
반면에 state는 컴포넌트 내부에서 선언하며 내부에서 값을 변경 할 수 있다.
State는 props처럼 App 컴포넌트의 렌더링 결과물에 영향을 주는 데이터를 갖고 있는 객체지만, props는 (함수 매개변수처럼) 컴포넌트에 전달되는 반면 state는 (함수 내에 선언된 변수처럼) 컴포넌트 안에서 관리된다는 차이가 있다.
props를 사용했는데도 state를 사용하는 이유는, 사용하는 쪽과 구현하는 쪽을 철저하게 분리시켜서 양쪽의 편의성을 각자 도모하는 것에 있다.
import React, { Component } from 'react';
class Counter extends Component {
this.state = {
number: 0
};
constructor(props) {
super(props);
this.handleIncrease = this.handleIncrease.bind(this);
this.handleDecrease = this.handleDecrease.bind(this);
}
handleIncrease() {
this.setState({
number: this.state.number + 1
});
}
handleDecrease() {
this.setState({
number: this.state.number - 1
});
}
render() {
return (
<div>
<h1>카운터</h1>
<div>값: {this.state.number}</div>
<button onClick={this.handleIncrease}>+</button>
<button onClick={this.handleDecrease}>-</button>
</div>
);
}
}
export default Counter;
일단 state는 화살표 함수를 사용해서 정의한다.
만약 사용하지 않는다면 위 코드와 같이 사용해야한다.
constructor를 사용하지 않으면 함수에서 작성한 this의 연결이 끊겨 버린다. 그래서 생성자인 constructor
를 사용해서 bind(this)로 묶어줘야한다.
import React, { Component } from 'react';
class Counter extends Component {
state = {
number: 0
}
handleIncrease = () => {
this.setState({
number: this.state.number + 1
});
}
handleDecrease = () => {
this.setState({
number: this.state.number - 1
});
}
render() {
return (
<div>
<h1>카운터</h1>
<div>값: {this.state.number}</div>
<button onClick={this.handleIncrease}>+</button>
<button onClick={this.handleDecrease}>-</button>
</div>
);
}
}
export default Counter;
하지만 화살표 함수를 사용하게 되면 좀 더 코드가 간결해지는걸 볼수있다.
이제 각 메소드에 들어있는 this.setState
에 대해서 알아보자. state에 있는 값을 바꾸기 위해서는 this.setState를 무조건 거쳐야한다. 리액트에서는 이 함수가 호출되면 컴포넌트가 리렌더링 되도록 설계 되어있고 setState는 객체로 전달되는 값만 업데이트를 해준다.
render 함수에서 이벤트 설정을 한 부분을 확인해보자
render() {
return (
<div>
<h1>카운터</h1>
<div>값: {this.state.number}</div>
<button onClick={this.handleIncrease}>+</button>
<button onClick={this.handleDecrease}>-</button>
</div>
);
}
어디서 많이 본 onClick
이 있다. 하지만 기존과는 다른점이 있는데
무조건 camelCase로 설정해주어야 한다.
예를 들어
onclick -> onClick
onmousedown -> onMouseDown
onchange -> onChange
이런식으로 말이다.
그리고 이벤트에 전달해주는 값은 함수여야 한다. onClick={this.handleIncrease()} 이런식으로 하게 된다면, 렌더링을 할 때 마다 해당 함수가 호출이 된다. 그렇게 되면 정말 큰 일이 발생한다. 렌더링 -> 함수 호출 -> setState -> 렌더링 -> 함수 호출 -> 무한반복.. 이렇게 되버린다. 진짜 지옥이다.
그래서 렌더링 함수에서 이벤트를 설정 할 때 만든 메소드를 호출하지 말자 !