React 공식문서 뜯어보기-State and LifeCycle
엘리먼트 렌더링에서는 UI를 업데이트하는 한가지 방법만 배웠으며, 렌더링 된 출력값을 변경하기 위해서 ReactDOM.render()
를 호출했습니다. 하지만 이번에는 컴포넌트를 완전히 재사용하고 캡슐화 하는 방법을 알아보겠습니다. 이 컴포넌트는 스스로 타이머를 설정하고 매초마다 스스로 업데이트 할 수 있도록 만들어 주겠습니다.
먼저 캡슐화를 시작해보겠습니다.
function Clock(props){
return (
<>
<h1>Hello!</h1>
<h2>It is {props.date.toLocaleTimeString()}.</h2>
</>
);
}
function tick(){
ReactDOM.render(
<Clock date={new Date()} />,
document.getElementById('root')
);
}
그러나 여기에는 중요한 요건이 누락되어 있습니다. Clock
이 타이머를 설정하고 매초 UI를 업데이트하는 것이 Clock
의 구현 세부사항이 되어야합니다. 이것을 구현하기 위해서는 Clock
컴포넌트에 state를 추가해야 합니다.
state는 props랑 유사하지만 state는 컴포넌트 안에서 관리되고 사용할 변수 선언과 비슷하게 사용할 수 있는 객체입니다.
새 로컬 State 추가하기
세 단계에 걸쳐서 date
를 props에서 state로 변경하겠습니다.
render()
메서드 안에 있는this.props.date
를this.state.date
로 변경합니다.
class Clock extends React.Component {
render() {
return (
<>
<h1>Hello!</h1>
<h2>It is {this.state.date.toLocaleTimeString()}</h2>
</>
);
}
}
- 초기
this.state
를 지정하는class constructor
를 추가합니다.
class Clock extends React.Component {
constructor(props){
super(props);
this.state = {date: new Date()};
}
render() {
return (
<>
<h1>Hello!</h1>
<h2>It is {this.state.date.toLcaleTimeString()}</h2>
</>
);
}
}
여기서 유의해야 할 것은 클래스 컴포넌트는 항상 props로 기본 constructor를 호출해야 합니다.
지금까지를 종합적으로 보게 된다면 다음과 같은 결과를 볼 수 있습니다.
class Clock extends React.Component {
constructor(props) {
super(props);
this.state = {date: new Date()};
}
render() {
return (
<>
<h1>Hello!</h1>
<h2>It is {this.state.date.toLocaleTimeString()}.</h2>
</>
);
}
}
ReactDOM.render(
<Clock />,
document.getElementById('root')
);
lifecycle 메서드를 클래스에 추가하기
React Components가 DOM에 마운트되고 해제되는 모든 과정을 React의 lifecycle 이라고 합니다. 컴포넌트 클래스에서 특별한 메서드를 선언해서 컴포넌트가 마운트되거나 언마운트 될 때 일부 코드를 작동할 수 있습니다. 이를 lifecycle method(생명주기 메서드)라고 불립니다.
지금까지의 예시에서 componentDidMount()
메서드는 컴포넌트 출력물이 DOM에 렌더링 된 후에 실행됩니다. 이 메서드 안에 타이머를 설정하기 좋을 것 같습니다.
componentDidMount() {
this.timerID = setInterval(
() => this.tick(),
1000
);
}
componentWillUnmount() {
clearInterval(this.timerID)
}
마지막으로 Clock
컴포넌트가 매초 작동하도록 하는 tick()
이라는 메서드를 구현하게 된다면 컴포넌트를 완성할 수 있습니다.
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 (
<>
<h1>Hello!</h1>
<h2>It is {this.state.date.toLocaleTimeString()}</h2>
</>
);
}
}
ReactDOM.render(
<Clock />,
document.getElementById('root')
);
State를 올바르게 사용하기
setState()
를 사용하면 주의해야할 점이 세가지가 있습니다.
직접 state를 수정해서는 안됩니다.
React는 virtualDOM과 기존의 DOM 모델을 비교해서 바뀐 부분이 있을 때만 필요한 부분만 다시 렌더링을 합니다. 하지만 직접 state를 변경했을 경우 이 부분을 확인 할 수 없기 때문에 state가 변경되어도 컴포넌트를 다시 렌더링 하지 않습니다.
state 업데이트는 비동기적으로 발생합니다.
React는 성능을 위해서 여러개의 setState()
호출을 단일 업데이트로 한꺼번에 처리할 수 있습니다. this.props
와 this.state
가 비동기적으로 업데이트 될 수 있기 때문에 다음 state를 계산할 때 해당 값에 의존해서는 안됩니다.
state 업데이트는 병합됩니다.
예를 들어, state는 다양한 독립적인 변수를 포함할 수 있습니다.
constructor(props) {
super(props);
this.state = {
posts: [],
comments: []
};
}
별도의 setState()
호출로 이러한 변수를 독립적으로 업데이트 할 수 있습니다.
componentDidMount() {
fetchPosts().then(response => {
this.setState({
posts: response.posts
});
});
fetchComments().then(response => {
this.setState({
comments: response.comments
});
});
}
하지만 병합은 얕게 이루어지기 때문에 this.setState({comments})
는 this.state.posts
에 영향을 주진 않지만 this.state.comments
는 완전히 병합됩니다.
데이터는 아래로 흐릅니다.
부모 컴포넌트나 자식 컴포넌트 모두 특정 컴포넌트가 유상태인지 또는 무상태인지 알 수 없고, 그들이 함수나 클래스로 정의되었는지에 대해서 관심을 가질 필요가 없습니다.
이 때문에 state는 종종 로컬 또는 캡슐화라고 불립니다. state가 소유하고 설정한 컴포넌트 이외에는 어떠한 컴포넌트에도 접근할 수 없습니다.
일반적으로 이를 “하향식(top-down)” 또는 “단방향식” 데이터 흐름이라고 합니다. 모든 state는 항상 특정한 컴포넌트가 소유하고 있으며 그 state로부터 파생된 UI 또는 데이터는 오직 트리구조에서 자신의 “아래”에 있는 컴포넌트에만 영향을 미칩니다.
트리구조가 props들의 폭포라고 상상하면 각 컴포넌트의 state는 임의의 점에서 만나지만 동시에 아래로 흐르는 부가적인 수원(water source)이라고 할 수 있습니다.
참고자료
Author And Source
이 문제에 관하여(React 공식문서 뜯어보기-State and LifeCycle), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@shallwedance/React-공식문서-뜯어보기-State-and-LifeCycle저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)