state

프로퍼티는 컴포넌트 내부에서 값을 바꿀 수 없다. 그러면 상품의 수량을 입력하거나, 댓글을 남기는 등 값을 바꿔야 하는 경우엔 어떻게 할까? state를 사용한다.

StateExample.jsx

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
import React, { Component } from 'react';

class StateExample extends Component {
constructor(props) {
super(props); //state 정의
//forceUpdate 사용시 this.loading=true; 와 같이 직접선언
this.state = {
loading: true,
formData: 'no data',
};
this.handleData = this.handleData.bind(this); //함수로 넘어갈 this는 반드시 생성자에서 bind로 묶어야함
setTimeout(this.handleData, 3000); //3초 후 저장된 값을 변경
}

handleData() {
const data = 'new data';
const { formData } = this.state; //특수변수 this.state를 사용하여 state값에 접근
//setState가 호출되면 자동으로 render함수가 호출됨
//직접 변경하고 검증없이 강제로 render함수를 실행하고 싶다면
//this로 접근해서 직접 바꾸고 this.forceUpdate() 사용
//but render에서의 접근은 this.state.data가 아닌 this.data로 접근
// this.loading = false;
// this.formData = data + this.formData;
// this.forceUpdate();

this.setState({
loading: false,
formData: data + formData,
});
console.log('loading값', this.state.loading);
}

//setState 함수의 인자로 함수를 전달하면 이전 state값을 쉽게 읽을 수 있음
handleData2(data) {
this.setState((prevState) => ({
loading: false,
formData: data + prevState.formData,
}));
}

render() {
return (
<div>
<span>로딩중: {String(this.state.loading)}</span>
<span>결과: {this.state.formData}</span>
</div>
);
}
}

export default StateExample;

기본적으로 state는

  • constructor에 선언
  • setState()로 변경

이렇게 사용한다.

setState()가 실행되면 검증 단계 후 자동으로 render()를 실행시키므로 별도의 새로고침 없이도 동적인 페이지에서 값이 바뀐다. 검증 단계를 거치기 싫고 강제로 값을 바꿔 새로고침을 만들고 싶다면 forceUpdate()를 사용하면 되는데, 자세한 설명은 위 코드 내에 주석으로 해놓았다.

그리고 중요한 것은, 함수로 넘어갈 this는 반드시 생성자 constructor에서 bind() 함수로 묶어주어야 한다.

이전 상태와 함께 사용하기

상태를 바꿀 때 이전 상태가 필요한 경우가 있다. count를 1씩 증가시키는 예제로 살펴보자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import React, { Component } from 'react';

class Counter extends Component {
constructor(props) {
super(props);
this.state = {
count: 0,
};
//state 정의
this.increaseCount = this.increaseCount.bind(this);
}

increaseCount() {
this.setState((prev) => ({ count: prev.count + 1 }));
}

render() {
return (
<div>
<span>카운트: {this.state.count}</span>
<button onClick={this.increaseCount}>카운트 증가</button>
</div>
);
}
}

export default Counter;

count이전 값 + 1 해줘야 하므로 이전 state에 대한 접근이 필요한데, 이 때 setState의 첫 번째 인자로 이전 상태에 접근할 수 있다.