해당 글은 리액트에서 제공하는 자습서에 내용을 덧붙이고 풀어서 작성한 글입니다.
원문 : https://ko.reactjs.org/docs/getting-started.html
이전 포스팅에서 props에 대해서 알아보았습니다.
props는 컴포넌트에 프로퍼티로 전달되고, 읽기전용입니다.
이번 포스팅에서는 read write둘다 할 수 있는 state라는 개념에 대해서 알아보겠습니다.
1초마다 째깍대는 시계 만들기
Clock컴포넌트 생성하기
<Clock />
컴포넌트 내부에서 모든것이 통제되는 캡슐화된 Clock 컴포넌트를 만들것입니다.
기존 src폴더 내부에 components폴더를 생성하고, components폴더 안에 Clock.js파일을 만들어줍니다.
폴더 구조는 위와 같습니다.
이전 까지는 함수 컴포넌트만 다뤘는데, 이번에는 클래스로 컴포넌트를 정의해보겠습니다.
Clock.js파일에 기본 컴포넌트 코드를 작성해줍니다.
import React, { Component } from "react";
class Clock extends Component{
render() {
return (
<div>
Clock Component
</div>
);
}
}
export { Clock }
가장 첫줄에 React 와 Component를 import한 뒤, class를 선언하고 Component를 상속시켜줍니다.
클래스 내부에 render함수의 return값이 해당 컴포넌트에 렌더링 되는 요소들입니다.
마지막 줄에 export를 해주어야 외부 파일에서 컴포넌트를 불러서 사용할 수 있습니다.
State사용하기
state를 사용하기 위해선 constructor를 이용해서 초기 state를 지정해주어야 합니다.
방금 작성한 Clock.js파일의 render함수 위에 constructor를 작성해줍니다.
import React, { Component } from "react";
class Clock extends Component{
//추가
constructor(props) {
super(props);
this.state = {
date : new Date()
};
}
render() {
return (
<div>
Clock Component
</div>
);
}
}
export { Clock }
생성자에서 state를 정의해주었습니다. date라는 state를 만들었고, 초기값은 생성된 당시의 시간을 담고있는 date객체입니다.
이제 this.state.date로 date에 접근할 수 있습니다.
이제 render내부의 내용을 바꿔보겠습니다.
import React, { Component } from "react";
class Clock extends Component{
constructor(props) {
super(props);
this.state = {
date : new Date()
};
}
render() {
return (
<div>
{/*수정*/}
<h2> 현재 시간은 ?? </h2>
<div>{ this.state.date.toLocaleTimeString() }</div>
</div>
);
}
}
export { Clock }
이때 date에는 date객체가 들어가 있기 때문에 date객체 내장 함수인 toLocaleTimeString을 불러 현재 시간을 가져올 수 있습니다.
정상적으로 현재 시간이 출력되는 것을 볼 수 있습니다.
이제 생명주기를 이용해서 매초 업데이트 되게 만들어 보겠습니다.
컴포넌트 생명주기
Clock컴포넌트가 DOM에 렌더링 될 때, 타이머를 작동시키고, DOM이 삭제 될 때 타이머를 해제 하려고 합니다.
DOM에 렌더링 되는 것을 마운트라고 합니다.
이를 구현하기 위해선 두가지 생명주기 메서드를 이용합니다.
componentDidMount() {
//마운트 될 때 수행되는 것
}
componentWillUnmount() {
//언마운트 될 때 수행되는 것
}
이외에도 많은 상황에서의 생명주기 메서드들이 있습니다.
setInterval을 이용해 1초마다 작동하는 타이머를 설정해보겠습니다.
import React, { Component } from "react";
class Clock extends Component{
constructor(props) {
super(props);
this.state = {
date : new Date()
};
}
//추가
componentDidMount() {
this.timer = setInterval(
() => this.tick(),
1000
);
}
componentWillUnmount() {
clearInterval(this.timerID);
}
tick() {
this.setState(
{date : new Date()}
)
}
render() {
return (
<div>
<h2> 현재 시간은 ?? </h2>
<div>{ this.state.date.toLocaleTimeString() }</div>
</div>
);
}
}
export { Clock }
setInterval은 첫번째 인자로 일정시간마다 수행될 함수를, 두번째 인자로 몇 밀리세컨드간격으로 수행할 건지를 지정하여 사용합니다.
this.timer처럼 굳이 state로 관리해주지 않아도 되는 경우 직접 추가해서 사용해도 됩니다.
위의 코드의 흐름을 설명하자면, componentDidMount에 1초마다 tick()을 실행하는 타이머를 작성해서 컴포넌트가 마운트 될 때 타이머가 등록되게 설정합니다.
그리고 마찬가지로 언마운트 될 때 clearInterval을 호출해서 등록한 타이머를 지워줍니다.
tick()에서는 setState로 state값을 지정해주는 것을 볼 수 있습니다.
this.setState({state이름:변경할값})처럼 사용할 수 있습니다.
여기서 중요한것은 state는 반드시 setState로 지정해주는 것이 좋습니다.
state가 props등 다른 값들과는 비동기적으로 업데이트 될 수 있기 때문에, 우리가 예상한 값과 다르게 동작할 수 있습니다.
이제 지속적으로 업데이트 되는 시계 컴포넌트가 완성되었습니다.
State에 관한 이야기
state는 직접 설정하지 않는 이상 부모 컴포넌트, 자식컴포넌트가 알 수 없습니다.
이번 예제에서도 Clock컴포넌트의 부모컴포넌트는 현재시간에 관심이 없기 때문에 Clock컴포넌트 내부에 state로 date를 만들어 주었습니다.
만약 자식컴포넌트에게 state값을 넘겨주고 싶다면 어떻게 해야할까요?
이때는 props로 state를 넘겨줄 수 있습니다.
만약 현재 시간 값(date객체)을 받아서 12시 7분 55초와 같이 포맷팅을 해주는 컴포넌트(FormattedDate)가 있다고 생각해봅시다.
이를 구현하기 위해서 FomattedDate컴포넌트는 현재 시간정보가 필요합니다.
<FormattedDate date={this.state.date}/>
이처럼 state값을 자식의 props로 넘겨줄 수 있습니다. 이때 FormattedDate에서는 해당 date값이 Clock에서의 state인지, Clock의 props인지, 직접 입력한 값인지 알 수 없습니다.
state는 자식의 props 로 넘겨주어 공유할 수 있고, state가 setState에 의해 업데이트 되면, 자식의 props도 같이 업데이트 됩니다.
이처럼 상위 컴포넌트에서 하위 컴포넌트로 state가 이동하는 것을 하향식 데이터 흐름이라고 부릅니다.
'Develop > React' 카테고리의 다른 글
[React] 리액트 기초 배우기 #6 조건부 렌더링 (0) | 2020.05.01 |
---|---|
[React] 리액트 기초 배우기 #5 이벤트 처리하기 (0) | 2020.04.27 |
[React] 리액트 기초 배우기 #3 components와 props (0) | 2020.04.26 |
[React] 리액트 기초 배우기 #2 JSX란? (0) | 2020.04.26 |
[React] 리액트 기초 배우기 #1 Hello React! 리액트 프로젝트 생성과 빌드 (0) | 2020.04.26 |