리엑트 컴포넌트 상태(state, props)에 대한 설명

state와 props의 차이점

state와 props(properties의 축약형)는 둘다 자바스크립트 객체입니다.
둘다 렌더링 결과에 영향을 주는 정보들을 가지고 있지만 한가지 중요한 점이 다릅니다.
props는 함수의 파라미터와 같이 컴포넌트를 통과합니다.
반면에 state는 함수 안에 선언된 변수와 같이 컴포넌트 안에서만 상태를 관리합니다.

setState()

setState()는 컴포넌트의 state 객체를 업데이트 하는 함수 입니다.
state가 변경되면 render()가 호출되어 컴포넌트에 상태가 반영됩니다.

setState()는 비동기로 호출 되지만 이벤트 핸들러 안에서 동기적으로 실행됩니다.
예를 들어, 클릭 이벤트 핸들러 함수 안에서 부모와 자식이 setState를 호출하면 자식은 두번 렌더링 하지 않습니다.
리엑트는 브라우저 이벤트가 끝날 때 state 업데이트를 반영합니다.
그 결과로 눈에 띄는 성능 향상이 됩니다.

리엑트는 다시 렌더링 되기 전에 모든 컴포넌트가 컴포넌트 이벤트 핸들러 안에서 setState()를 호출할 때까지 대기합니다.
이것은 불필요한 렌더링을 피함으로서 성능 향상이 됩니다.

setState가 잘못된 값을 주는 이유

리엑트에서는 this.props와 this.state는 현재 화면에 표시된 렌더링된 값을 표현합니다.

예상대로 작동하지 않는 코드 예

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
incrementCount() {
// 아래 코드는 의도한 대로 동작하지 않습니다.
this.setState({count: this.state.count + 1});
}

handleSomething() {
// `this.state.count`는 0부터 시작합니다.
this.incrementCount();
this.incrementCount();
this.incrementCount();
// 리엑트가 컴포넌트를 다시 렌더링할때 this.state.count는 1이고 3이 아닙니다.

// incrementCount()함수는 this.state.count의 값을 사용하지만
// 리엑트가 다시 렌더링 되기 전까지 this.state.count값을 업데이트 하지 않습니다.
// 그래서 incrementCount()는 this.state.count를 매번 0으로 읽고 1로 할당합니다.

}

수정된 코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
incrementCount() {
this.setState((prevState) => {
// 업데이트를 할 때 this.state대신 prevState 값을 읽어야 합니다.

return {count: prevState.count + 1}
});
}

handleSomething() {
// `this.state.count`는 0부터 시작합니다.
this.incrementCount();
this.incrementCount();
this.incrementCount();

// 현재 `this.state.count` 값은 0이고 리엑트가 컴포넌트를 다시 렌더링하면 3이 됩니다.

}

resource