2022. 5. 14. 17:50ㆍ공부/React
이전에 엘리먼트의 렌더링은 동영상의 프레임처럼 한 장면만을 나타낸다고 했다.
그에 따라 새롭게 바뀌는 부분이 있으면 ReactDOM.render()를 통해 재 랜더링을 했어야 했다.
Clock 컴포넌트를 완전히 재사용하고 캡슐화하게 되면
스스로 타이머를 설정하고, 업데이트 하도록 만들 수 있다.
캡슐화
먼저 구조부분을 Clock() 함수 컴포넌트로 분리시킨다.
이후, Clock이 타이머를 설정하고 매초 UI를 업데이트 하는 로직을 구성하기 위해선 "State"라는 개념이 필요하다.
State
props와 유사하지만 비공개이고, 컴포넌트에 의해 완전히 제어되는 요소들이다.
props 또는 State가 업데이트 되면 React는 다시 렌더링하게 된다.
정의 방식은 다음과 같다.
// 방식 1
class Component extends React.Component {
state = {
s: '스테이트'
};
render() {
return {
<div>{this.state.s}</div>
}
}
}
// 방식 2
class Component extends React.Component {
constructor(props) {
super(props);
this.state = {s: '스테이트'};
}
render() {
return {
<div>{this.state.s}</div>
};
}
}
이처럼 state에 바로 정의를 할 수도 있고, class constructor 내부에 정의할 수 있다.
setState()
state의 값을 변경하기 위해서는 this.state.s 처럼 바로 접근해서 사용하면 안된다.
변경하기 위해서는 this.setState() 메소드를 이용하여 변경해야 한다.
this.setState({
count: this.state.count + 1
});
State와 Props의 업데이트는 비동기적일 수 있다.
따라서 이전 값을 가져와서 State를 계산하고 싶다면 다음처럼 사용해선 안된다.
// Wrong
this.setState({
counter: this.state.counter + this.props.increment,
});
이를 해결하기 위해선 함수를 인자로 받는 setState()를 사용해야 한다.
첫번째 인자로는 이전 state가 들어오고, 두번째 인자로는 업데이트가 적용된 시점의 props가 들어오게 된다.
// Correct
this.setState((state, props) => ({
counter: state.counter + props.increment
}));
함수에서 클래스로 변환하기
다음의 단계를 통해 함수에서 클래스 컴포넌트로 변환할 수 있다.
- React.Component를 상속받는 동일한 이름의 ES6 Class를 생성한다.
- render() 메소드를 추가한다.
- 함수의 내용을 render() 메소드 안으로 옮긴다.
- render() 내용 안의 props를 this.props로 변경한다.
- 기존의 함수를 제거한다.
클래스에 로컬 State 추가하기
1. render() 메소드 안에 있는 this.props.date를 this.state.date로 변환
2. 초기의 this.state를 지정하는 class constructor를 추가한다.
클래스 컴포넌트는 항상 props로 기본 constructor를 호출해야 한다.
3. <Clock /> 요소에서 date prop을 삭제한다.
아직 매 초마다 렌더링을 다시 하는 로직은 구현되지 않았다. 이를 구현하려면 컴포넌트 생명주기 개념이 필요.
컴포넌트 생명주기
위처럼 여러 생명주기 메소드들이 존재한다.
컴포넌트 생성 및 마운트 관련 (16.3 버전 미만)
- componentWillMount()
- render()
- componentDidMount()
컴포넌트 props, state 변경 관련 (16.3 버전 미만)
- componentWillReceiveProps(nextProps) : 바뀌게 되는 props를 받는 시기
- props를 새로 지정했을 때 바로 호출됨.
- 여기서 state를 변경시켜도 반응하지는 않는다.
- props 값에 따라 state를 변경해야 하면 setState를 통해 변경해야 한다.
- 변경은 순차적이지 않고 한번에 이루어진다.
- shouldComponentUpdate(nextProps, nextState) : 재 랜더링 여부를 결정하는 시기
- props 또는 state가 변경되면 nextProps와 nextState를 인자로 해서 호출된다.
- return type은 Boolean type이다.
- true면 렌더링 되고, false면 되지 않는다.(디폴트 값: true)
- componentWillUpdate(nextProps, nextState)
- 컴포넌트가 재 렌더링 되기 직전에 호출됨.
- setState 사용 불가
- render
- componentDidUpdate(prevProps, prevState)
컴포넌트 언마운트 관련 (16.3 버전 미만)
- componentWillUnmount
컴포넌트 에러 캐치
- componentDidCatch
16.3 버전 이상에서 라이프사이클의 변경
- componentWillMount => getDerivedStateFromProps
- componentWillReceiveProps => getDerivedStateFromProps
- componentWillUpdate => getSnapshotBeforeUpdate
생명주기 메소드를 클래스에 추가하기
Clock이 처음 DOM에 렌더링이 되면 타이머를 설정하고 (마운팅)
Clock에 의해 생성된 DOM이 삭제될 때마다 타이머를 해제하려고 한다. (언마운팅)
이렇듯, 컴포넌트가 마운트 되거나 언마운트 될 때 일부 생명주기 코드를 사용할 수 있다.
componentDidMount()
컴포넌트 출력물이 DOM에 렌더링 된 후에 실행된다. 타이머를 설정하기 좋은 장소
componentWillUnmount()
언마운트 되기 전에 사용한 리소스들을 확보하는 시기다.
tick() 메소드 구현
요약
1. <Clock />가 ReactDOM.render()로 전달되면, constructor()가 호출된다.
- new Date()에 의해 현재 시각이 this.state.date에 저장되며 초기화된다.
2. React가 Clock 컴포넌트의 render() 메소드를 호출한 뒤, DOM을 업데이트 한다.
3. Clock 출력값이 DOM에 삽입되면, componentDidMount() 생명주기 메소드가 호출된다.
- this.timerID 에 저장된 setInterval() 함수가 작동하여 1초 뒤에 tick() 메소드를 작동시킨다.
4. tick() 함수에 this.setState가 새롭게 Date() 함수를 통해 this.state.date를 갱신한다.
- React는 setState의 작동을 감지하여 다시 렌더링한다.
- 즉 1초마다 tick() 함수가 반복적으로 실행되게 된다.
5. Clock 컴포넌트가 DOM으로부터 한번이라도 삭제된다면, componentWillUnmount()를 통해 타이머가 삭제된다.
'공부 > React' 카테고리의 다른 글
[React 주요 개념] 06. Event Handling (0) | 2022.05.14 |
---|---|
[React 주요 개념] 05. 라이프사이클 변경점 (0) | 2022.05.14 |
[React 주요 개념] 03. Component와 Props (0) | 2022.05.14 |
[React 주요 개념] 02. 엘리먼트 렌더링, Virtual DOM (0) | 2022.05.14 |
[React 주요 개념] 01. JSX (0) | 2022.05.14 |