이전에 배웠던 Props는 부모 컴포넌트에서 자식 컴포넌트로 특정 원하는 값을 내려주어 렌더링 하는 방식이라면 state는 말 그대로 컴포넌트 내부에서 가지고 있는 상태 값입니다. Props는 읽기 전용이지만, state는 컴포넌트에서 언제든지 변경이 가능합니다.
간단하게 state를 사용하는 예제 코드에 대해서 살펴보겠습니다.
import React, { Component } from 'react';
class Counter extends Component {
state = {
number: 1
}
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;
모듈을 사용하기 위해서 항상 export를 해줘야 합니다. default 키워드는 모듈안의 개체가 하나일 때 사용합니다.
counter.js 파일을 만들고 내부에 Counter 컴포넌트를 생성하고 JSX 문법으로 값을 증감시키는 버튼을 만들어서 버튼을 통해서 값을 변경하는 예제 코드입니다.
그리고 App 컴포넌트에서 state를 가지고 있는 Counter 컴포넌트를 import하여 실제 html 페이지에서 Counter 컴포넌트가 랜더링한 페이지를 보여주고 있습니다.
import React, { Component } from 'react';
import './App.css';
import Counter from './Counter';
class App extends Component {
render() {
return <Counter/>;
}
}
export default App;
Counter 컴포넌트에서 state를 변경할 때 반드시 setState()를 사용해서 바꿔야 합니다. 만약 아래처럼 handleIncrease, handleDecrease() 메서드로 바꾸게 된다면 컴포넌트에서 state 값이 update가 되었는지 알 수가 없기 때문에 이렇게 변경하는건 절대 안됩니다.
handleIncrease = () => {
this.state.number = this.state.number + 1;
}
handleDecrease = () => {
this.state.number = this.state.number - 1;
}
올바른 예는 setState()를 사용하는 것입니다.
handleIncrease = () => {
this.setState({
number: this.state.number + 1
});
}
handleDecrease = () => {
this.setState({
number: this.state.number - 1
});
}
위의 코드를 보면 render() 메서드처럼 함수 선언식이 아니고 화살표 방식으로 함수를 생성한 이유는 선언식으로 생성할 경우에는 this.setState()에서 this가 Counter 컴포넌트에 바인딩이 되지 않아 정상적으로 setState()가 실행되지 않기 때문입니다.
화살표 함수는 자신만의 this를 갖지 않기 때문에, 바깥 스코프에서 this의 값을 계승받습니다. 그러나 이러한 특징 때문에 객체의 메소드로 화살표 함수를 사용하는 것은 적합하지 않습니다.
const person = {
name: "junyoung",
greet: () => console.log(`${this.name}`)
};
person.greet();
junyoung
위 예제에서 보듯이 바깥 스코프에서 this의 값을 계승받습니다. 즉, this는 메소드를 호출한 객체를 가르키지 않고 상위 컨텍스트인 전역 객체, window를 가리키게 됩니다. node.js일 경우 global을 가르킬 겁니다.
객체의 메소드에서는 화살표 함수가 아닌, function 문법 함수를 사용해야 합니다.
function 문법과 화살표 함수의 차이점은 function 문법에서 this는 함수가 어떻게 실행되는 가에 따라서 동적으로 바뀌게 됩니다. 반면에 화살표 함수의 경우 화살표 함수가 정의된 곳의 문맥에 의해서 this가 정의됩니다.