프로퍼티는 컴포넌트 내부에서 값을 바꿀 수 없다.
그러면 어떻게 바꾸나..
그렇다 state를 쓴다.
state로 상태 관리하기
state는 값을 저장하거나 변경할 수 있는 객체로 보통 버튼을 클릭하거나 값을 입력하는 등의 이벤트와 함께 사용된다.
다음은 setTimeout() 함수를 통해 4초 후 state에 저장되어 있는 값을 변경하는 예제다.
import React from 'react';
class StateExample extends React.Component {
constructor(props) {
super(props);
// state 정의
this.state = {
loading: true,
formData: 'no data',
};
this.handleData = this.handleData.bind(this);
setTimeout(this.handleData, 4000);
}
handleData() {
const data = 'new data';
const { formData } = this.state;
//state 변경
this.setState({
loading: false,
formData: data + formData,
});
//this.stateloading은 현재 true입니다.
console.log('loading값', this.state.loading);
//이후 호출될 render() 함수에서의 this.state.loading은 false입니다.
}
render() {
return (
<div>
{/* state 데이터는 this.state로 접근 가능합니다. */}
<span>로딩중: {String(this.state.loading)}</span>
<span>결과: {this.state.formData}</span>
</div>
);
}
}
export default StateExample;
state를 사용할 주의할 점
1. 생성자에서 반드시 초기화해야 한다.
2. state값을 변경할 때는 setState()함수를 반드시 사용해야 한다.
3. setState()함수는 비동기로 처리되며, setState()코드 이후로 연결된 함수들의 실행이 완료된 시점에서 화면 동기화 과정을 거친다.
생성자에서 초기화 해줄때, 초기값이 없더라도 state에 빈객체라도 넣어줘야 한다.(this.state = {};)
왜지.. 검색해도 잘 모르겠다.. 일단 넘어가자.. ㅠㅠㅠㅠㅠ
setState함수를 사용해야 하는 이유.
render()함수로 화면을 그려주는 시점은 리액트 엔진이 정한다. 따라서 내가 state를 직접 변경해도 render()함수는 새로 호출되지 않는다.
하지만 setState함수를 사용하지 않고도 state를 관리할 수 있는 방법이 있다.
클래스 인스턴스 변수와 forceUpdate() 함수로 state 관리하기
setState함수를 사용하는 이유는 리액트 엔진이 state 변경과 화면 동기화 과정을 처리하기 때문이다. 만약에 출력 검증 작업 없이 함수가 호출될 때마다 새롭게 화면을 출력하고 싶다면 클래스 인스턴스 변수와 화면을 강제로 출력해주는 forceUpdate()함수를 사용하면 된다.
import React from 'react';
class StateExample extends React.Component {
constructor(props) {
super(props);
// state 정의
this.state = {
loading: true,
formData: 'no data',
};
this.handleData = this.handleData.bind(this);
setTimeout(this.handleData, 4000);
}
handleData() {
const data = ' new data';
const { formData } = this.state;
//state 변경
this.setState({
loading: false,
formData: data + formData,
});
//this.stateloading은 현재 true입니다.
console.log('loading값', this.state.loading);
//이후 호출될 render() 함수에서의 this.state.loading은 false입니다.
}
render() {
return (
<div>
{/* state 데이터는 this.state로 접근 가능합니다. */}
<span>로딩중: {String(this.state.loading)}</span>
<span>결과: {this.state.formData}</span>
</div>
);
}
}
export default StateExample;
단 이 방법은 리액트 성능에 제약이 있으므로 매번 새롭게 화면을 출력해야 되는 경우가 아니라면 가급적 사용을 하지 않는것이 좋다.