state는 하나의 컴포넌트 안에서 전역 변수처럼 사용할 수 있는 것이다. this.state.변수명=value
와 같이 state를 직접 변경하면, render()
함수를 호출하지 않아서, 화면에 보이는 state값은 바뀌기 전 상태로 남게 된다. setState() 함수로 state를 변경해야, render()함수를 호출해 변경된 값을 화면에 보여줄 수 있다.
class R025_SetState extends Component {
constructor (props) {
super(props);
this.state = {
StateString : 'react',
}
}
StateChange = (flag) => {
if( flag == 'direct') this.state.StateString = "리액트";
if( flag == 'setState') this.setState({StateString : "리액트"});
}
state 변수 StateString의 초깃값으로 'react'라는 문자열을 저장하였다. constructor()함수가 실행되고, render()함수에서 화면을 그려내기 때문에 {this.state.StateString}은 react로 표시된다.
state값을 변경하기 위한 버튼을 render()로 화면에 뿌려보자.
render(){
return(
<div style = {{padding : "0px"}}>
<button onClick ={(e) => this.StateChange('direct', e)}>
state 직접 변경
</button>
<button onClick = {(e) => this.StateChange('setstate',e)}>
setState로 변경
</button><br/>
[state 변경하기] StateString : {this.state.StateString}
</div>
)
}
};
state직접 변경 버튼을 누르게 되면, this.state.StateString="리액트"
로, state의 값이 직접 바뀌게 된다. 이때 StateString값은 '리액트'로 변경되지만, render()함수를 호출하지 않으므로, 화면에는 이전 값인 'react가 여전히 출력된다!
자, 그럼 setState()함수로 state를 변경하는 버튼을 누르면 어떤 일이 일어나는지 보자
<button onClick = {(e) => this.StateChange('setstate',e)}>
setState로 변경
</button><br/>
[state 변경하기] StateString : {this.state.StateString}
화면이 다시 render되므로 바뀐 값이 출력된다!
setState() 함수로 state를 변경한다. 이 때, StateString을 '리액트'로 변경하고, render()함수를 다시 호출하여 화면에는 변경된 값인 '리액트'가 출몰하는 것이다.
다음 예제를 통해서 확인해보자.
constructor (props) {
super(props);
this.state = {
StateString : 'react',
StateArrayObj : ['react', {react : '200'}]
}
}
내가 선언을 이렇게 했다고 치자! 이 때 다음 버튼이 존재한다고 가정하자.
render() {
console.log('render()실행');
return (
<div>
<button onClick = { e => this.buttonClick('String')}> 문자열 변경</button>
<button onClick = { e => this.buttonClick('ArrayObject')}>객체 배열 변경</button>
</div>
)
}
그리고 위의 버튼을 누르면 아래 이벤트가 발생한다.
buttonClick = (type) => {
if(type === 'String'){
this.setState({ StateString : 'react'});
} else{
this.setState({StateArrayObj : ['react ', { react : '200'}]});
}
};
문자열 변경 버튼을 누르게 되면 처음에 선언한 문자열 변수와 동일한 state값으로 변경을 시키는데도 컴포넌트는 state값이 변경되었다고 간주하여 render()함수를 실행한다.
또한, 객체 배열 변경 버튼을 클릭하면 내가 선언하였던 state값과 동일한 값으로 setState()함수를 이용하여 선언 및 초기화한다. 이때 컴포넌트는 state값이 변경되었다고 간주하여, render()함수를 동일하게 실행시킨다.
setState()함수로 실행한 값은, 이전에 있던 state 변숫값과 동일하더라도, Component에서는 새로운 state 변수가 같은 이름으로 생성되었다고 인식하는 것이다.
그럼 매일 이렇게 render()가 일어나는게 싫어!! 그럼 어떻게 해야 하나?
class형 컴포넌트에서, Component를 사용하지 말고 PureComponent를 사용한다 이 친구는 비교 대상의 값을 비교하여, 동일하지 않으면 변경이 발생하였다고 취급한다. 이 친구는 위와 같은 과정이 일어났을 때, state값이 동일하다고 간주하여 render()함수를 실행하지 않는다.
PureComponent에서 새로운 state 변수가 선언되었지만, 변숫값만 비교하는 것이다.
하지만 이 친구도 예외는 있다. 객체에 대해서는 참조 값을 비교한다. 객체의 데이터는 같지만, 참조의 값이 달라서 다른 객체로 인식한다. (참조 값은 객체를 생성하였을 때 저장되는 메모리 주소이다. 완전히 동일한 데이터값을 가지고 있다고 해도, 새로 선언하게 되면 다른 참조 값을 가진다.)
그럼 PureComponent는 어떻게 사용하냐고?..이렇게다.
import React, { PureComponent } from 'react';
class R027_ComponentClass extends PureComponent ....
그건 아니다. 하지만 비추...그래도, 우리가 state값을 직접 변경해야하는 상황을 마주하게 될 수도 있으니까, 어떻게 해야 하는지만 알아보도록 하자.
this.state.변수명 = value와 같이 직접 state를 변경하면, render()함수를 호출하지 않으므로 화면에 보이는 state값은 바뀌기 전의 상태로 남게 된다.이 때 forceUpdate()함수를 이용하여 화면을 새로고침할 수 있다. 이 새로고침으로 인하여 render()함수가 호출되어, 변경된 값을 화면에 보여줄 수 있다.
StateChange = (flag) => {
this.state.StateString = "리액트";
this.forceUpdate();
}
이렇게!! forceUpdate()를 통하여 직접 값을 변경하는 것이다~ (근데비추함)ㅋ