- 지금까지의 컴포넌트는 무상태 컴포넌트 였다. 부모로 부터 받은 속성은 있으나, 실행될 때 그 속성에 관한 어떤 변화도 일으키지 않았다.
- 하지만 사용자와의 상호작용 결과로 컴포넌트의 어떤 부분은 변경되거나, 서버로부터 데이터를 가지고 오거나, 그밖에 무수히 많은 일들이 일어날수 있다.
즉 .. 우리에게 필요한것은
>> 속성의 수준을 넘어 컴포넌트에 데이터를 저장하는 또 다른 방법이다.
>. 이는 변경되는 데이터를 저장해야 한다는 의미이다. 그 데이터를 바로 상태(state) 라고 한다.
1. 상태 사용하기
-- 간단한 앱을 만들어 실습해보도록 하자 (번개친 횟숫 카운트하기)
>> LightningCounterDisplay 라는 컴포넌트는
render() 에서 스타일 객체를 만들어 <div> 태그에 스타일을 지정하고 <LightningCounter/>를 호출 하고 있다.
>> LightningCounter 에서는 단지 <h1>Hello</h1>을 리턴할 뿐이다.
ReactDOM.render() 함수에서는 LightningCounterDisplay 컴포넌트를 DOM 안의 container 엘리먼트에 넣고 있다
최종 결과는 LightningCounterDisplay 와 LightningCounter 컴포넌트 그리고 ReactDOM.render 메소드가 조합된 마크업이다.
2. counter 키기
>> 이제 Counter를 한번 켜보도록 하자 (LightningCounter 부분을 다룰예정)
1) 초기 상태 값 설정
strikes 변수를 설정하는데 이 변수는 컴포넌트 상태의 일부분 이다. 따라서 state 객체를 만들고 그 속성으로 strikes 변수를 사용함으로써 컴포넌트가 생성될 때 그 모든 준비가 되게 끔 진행할 것이다.
2) 타이머 가동과 상태 설정
- 이제 타이머를 시작 시키고 strikes 속성 값을 증가 시켜야 할 차례이다. setInterval 함수를 사용해 strikes 속성을 매초마다 100씩 증가 시킬것이다. 이는 컴포넌트가 렌더링된 직후에 실행되는 componentDidMount() 메서드를 이용하면된다.
- componentDidMount() 메서드는 렌더링 된 후 한번 호출 되므로, 그 안에 매초마다 timeTick() 함수를 호출하는 setInterval() 를 추가해 줬다.
- 또한 timerTick() 를 정의해 주었다.
- 컴포넌트에 timerTrick 함수는 추가되었지만, 그 콘텐츠에 컴포넌트의 컨텍스트가 유지되지는 않는다
- 현재 상황에서는 this.setState는 typeError를 리턴할것이다.
- 일단 지금은 timerTick 함수를 컴포넌트에 명시적으로 바인딩 시키는 방법을 사용하자.
- 생성자에서 timerTick 을 bind 시켜주었다.
그러면 이제 앱을 테스트 해보도록 하자
마지막으로 정리를 해보자면
ReactDOM.render() 를 통해서 <LightningCounterDisplay / > 컴포넌트가 #container 의 div안으로 들어 가게 되고
LightningCounterDisplay 컴포넌트에서는 <LightningCOunter/> 컴포넌트를 <div style={divStyle}> 태그로 둘러 싸서 리턴해 준다. LightningCounter에서는 컴포넌트가 렌더링 되면 생성자에 의해서 state 객체가 생성되고 strikes = 0으로 초기화 시켜준다. 그 후 렌더링 후 실행되는 componentDidMount() 함수가 호출되면서 내부에 있던 setInterval() 함수를 통해 1초마다 timerTick() 함수를 호출해 준다. 이때 생성자에서 timerTick() 함수를 사용하기 위해서 bind 해주는 모습을 볼수 있었다. 그후 {this.state.strikes} 를 리턴해주면서 1초마다 100씩 증가하는 것을 확인 할 수 있다.
-- 이때 setState({}) 함수를 통해 state 객체에 어떤 내용이 변경될때마다 컴포넌트의 render 메소드가 자동으로 호출된다.이는 연관된 다른 모든 컴포넌트들의 render함수를 연쇄적으로 호출한다.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/babel-standalone@6.15.0/babel.min.js"></script>
<style>
</style>
</head>
<body>
<div id="container"></div>
<script type="text/babel">
class LightningCounter extends React.Component{
constructor(props){
super(props);
this.state = {
strikes : 0
};
this.timerTick = this.timerTick.bind(this);
}
timerTick(){
this.setState({
strikes : this.state.strikes + 100
});
}
componentDidMount(){
setInterval(this.timerTick, 1000);
}
render(){
var counterStyle = {
color : "#66ffff",
fontSize : 50
}
var count = this.state.strikes.toLocaleString();
return(
<h1>{this.state.strikes}</h1>
)
}
}
class LightningCounterDisplay extends React.Component{
render(){
var commonStyle ={
margin : 0,
padding : 0
}
var divStyle = {
width : 250,
textAlign : "center",
backgroundColor : "#020202",
padding : 40,
fontFamilty : "sans-serif",
color : "#999",
borderRadius : 10
}
var textStyles = {
emphasis : {
fontSize : 38,
...commonStyle
},
smallEmphasis : {
...commonStyle
},
small : {
fontSize : 17,
opacity : 0.5,
...commonStyle
}
};
return(
<div style={divStyle}>
<LightningCounter/>
<h2 style={textStyles.smallEmphasis}>LIGHTNING STRIKES</h2>
<h2 style={textStyles.emphasis}>WORLDWIDE</h2>
<p style={textStyles.small}>(since you loaded this example)</p>
</div>
)
}
}
ReactDOM.render(
<LightningCounterDisplay/>
, document.querySelector("#container")
);
</script>
</body>
</html>
'dev > React' 카테고리의 다른 글
[React] 이벤트 (0) | 2022.11.30 |
---|---|
[React] 데이터에서 UI로 (0) | 2022.11.30 |
[REACT] JSX 특징 (0) | 2022.11.30 |
[React] 속성 전달 (0) | 2022.11.29 |
[React] 복잡한 컴포넌트 제작 (0) | 2022.11.29 |