참고로 React 정리를 어떻게 할까 고민하다가 React 공식 사이트의 Docs를 읽어보고 정리하기로 정했다. 누군가가 내 글을 보고 부족함을 느낀다면 React 공식 Docs를 찾아보길 권한다.
State
State를 공부하기 위해 Clcok 컴포넌트를 만들어 보자.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function Clock(props) {
return (
<div>
<h1>{new Date().toLocaleTimeString()}</h1>
</div>
);
}
function tick() {
ReactDOM.render(
<Clock date={new Date()} />,
document.getElementById('root')
);
}
setInterval(tick, 1000);
위 코드에서 매 초마다 tick 함수를 호출하고 Clock에 새로운 시간을 props로 넘겨서 다시 렌더링한다. 이상적인 Clock은 시간을 스스로 업데이트하는 방법일 것이다. 그러기 위해서 props로 받는 시간을 Clock 내부에서 state로 만들어야 한다. state는 props와 유사하지만 state는 private하고, 철저히 component에 의해 통제되어야 한다.
state를 Clock 내부에 만들기 위해 function을 class로 바꿔보자.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Clock extends React.Component {
constructor(props) {
super(props);
this.state = {date: new Date()};
}
render() {
return (
<div>
<h1>{this.state.date.toLocaleTimeString()}</h1>
</div>
);
}
}
ReactDOM.render(
<Clock />,
document.getElementById('root')
);
render 함수는 업데이트가 발생할 때 마다 호출된다. 하지만 동일한 DOM node 내부에서 그려지는 Clock은 단 하나의 객체로 사용된다.
Lifecycle Methods
Clock이 처음 그려질 때 타이머가 설정이 되고, Clock이 지워질 때 타이머도 지워져야 한다. React에서 이것을 “mounting” / “unmounting” 이라 한다.
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
class Clock extends React.Component {
constructor(props) {
super(props);
this.state = {date: new Date()};
}
componentDidMount() {
this.timerID = setInterval(
() => this.tick(), 1000
);
}
componentWillUnmount() {
clearInterval(this.timerID);
}
tick() {
this.setState({
date: new Date()
});
}
render() {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {this.state.date.toLocaleTimeString()}.</h2>
</div>
);
}
}
ReactDOM.render(
<Clock />,
document.getElementById('root')
);
여기서 componentDidMount()와 componentWillUnmount()를 “lifecycle method”라고 한다.
componentDidMount() method는 component 결과가 렌더링 된 후에 실행된다.
componentWillUnmount() method는 component가 제거될 때 실행된다.
State 사용 시 주의사항
1. Do Not Modify State Directly(State를 직접 변경하지 말 것)
state는 setState() 함수를 사용해서 변경해야하며, class형 컴포넌트에서는 오직 constructor의 this.state에서 할당할 수 있다.
2. State Updates May Be Asynchronous(State Update는 비동기적으로 동작한다.)
얼마전 React 공부 중 만났던 오류의 내용이였다. React를 쓰다보면 하나의 업데이트 함수 내부에서 여러 개의 State를 변경해야 하는 경우가 생긴다.
그 때 만약 그 State들이 서로 영향을 주는 관계가 있다면, 원하는 대로 렌더링 되지 않을 것이다. 하지만 실제로 State 업데이트는 제대로 이루어 진 것을 확인할 수 있다!!
그 원인이 State Update가 비동기적으로 이루어지기 때문이다.
3. State Updates are Merged(State Update는 병합된다.)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
constructor(props) {
super(props);
this.state = {
posts: [],
comments: []
};
}
componentDidMount() {
fetchPosts().then(response => {
this.setState({
posts: response.posts
});
});
fetchComments().then(response => {
this.setState({
comments: response.comments
});
});
}
state의 각 요소를 독립적으로 업데이트 할 수 있다.