React 기초
[React] State와 생명주기 (4)
Evolving Developer
2023. 2. 7. 22:15
시계 예제
const root = ReactDOM.createRoot(document.getElementById('root'));
function Clock(props) {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {props.date.toLocaleTimeString()}.</h2>
</div>
);
}
function tick() {
root.render(<Clock date={new Date()} />);
}
setInterval(tick, 1000);
- 1초마다 <Clock/>을 새롭게 렌더링하는 방법
-> <Clock/>이 스스로 업데이트하도록 만들고 싶다면?
함수에서 클래스로 변환하기
1. React.Component를 확장하는 동일한 이름의 class를 생성
class Clock extends React.Component
2. render()라고 불리는 빈 메서드 추가
- 업데이트가 발생할 때마다 호출됨
class Clock extends React.Component {
render() {
}
}
3. 함수의 내용을 render() 메서드 안으로 옮김
4. render() 내용 안에 있는 props를 this.props로 변경
class Clock extends React.Component {
render() {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {this.props.date.toLocaleTimeString()}.</h2>
</div>
);
}
}
props에서 state로 변경하기
1. render() 메서드 안에 this.props.date -> this.state.date로 변경
class Clock extends React.Component {
render() {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {this.state.date.toLocaleTimeString()}.</h2>
</div>
);
}
}
2. 초기 this.state를 지정하는 class constructor 추가
class Clock extends React.Component {
constructor(props) {
super(props);
this.state = {date: new Date()};
}
render() {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {this.state.date.toLocaleTimeString()}.</h2>
</div>
);
}
}
- 클래스 컴포넌트는 항상 props로 기본 constructor를 호출
3. <Clock /> 요소에서 date 관련 코드 삭제
root.render(<Clock />);
전체 코드
class Clock extends React.Component {
constructor(props) {
super(props);
this.state = {date: new Date()}; // state 변수에 현재 시간을 담음 (고정값)
}
render() {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {this.state.date.toLocaleTimeString()}.</h2>
</div>
);
}
}
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<Clock />);
- 순간의 시간에 멈춰있는 결과가 출력됨 ex) It is 오후 8:51:40.
-> 초마다 업데이트 되게 하고 싶다면?
생명주기 메서드를 클래스에 추가하기
class Clock extends React.Component {
constructor(props) {
super(props);
this.state = {date: new Date()};
}
componentDidMount() {
}
componentWillUnmount() {
}
render() {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {this.state.date.toLocaleTimeString()}.</h2>
</div>
);
}
}
1. componentDidMount()
componentDidMount() {
this.timerID = setInterval( // timerID라는 새 변수 추가
() => this.tick(), // 초마다 tick() 함수 실행
1000
);
}
2. componentWillUnmount()
componentWillUnmount() {
clearInterval(this.timerID);
}
3. tick()
tick() {
this.setState({ // state 변수의 값을 세팅
date: new Date()
});
}
전체 코드
class Clock extends React.Component {
constructor(props) {
super(props);
// 2. 현재 시간을 보여줘야 하기 때문에 현재 시각이 포함된 객체로 state 초기화
this.state = {date: new Date()};
}
// 4. 생명 주기 메서드 호출
componentDidMount() {
this.timerID = setInterval( // 매초 tick() 메서드 호출
() => this.tick(),
1000
);
}
// 6. Clock 컴포넌트가 DOM으로부터 한 번이라도 삭제된 적이 있다면 React는 타이머를 멈춤
componentWillUnmount() {
clearInterval(this.timerID);
}
// 5. tick() 메서드 호출
tick() {
this.setState({ // state 값을 현재 시각으로 업데이트 -> 다시 rendering
date: new Date()
});
}
// 3. render() 함수 호출 & state 내 date에 접근
render() {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {this.state.date.toLocaleTimeString()}.</h2>
</div>
);
}
// 1. <Clock />이 root.render()로 전달될 때, Clock 컴포넌트의 constructor 호출
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<Clock />);
State를 올바르게 사용하기
1. state를 직접 수정하지 않는다.
- 대신 setState()를 사용
- constructor는 this.state를 지정할 수 있는 유일한 공간
// Wrong
this.state.comment = 'Hello';
// Correct
this.setState({comment: 'Hello'});
2. state는 비동기적
- React는 성능을 위해 여러 setState() 호출을 단일 업데이트로 한꺼번에 처리할 수 있음
// Wrong
this.setState({
counter: this.state.counter + this.props.increment,
});
- 객체보다는 함수를 인자를 사용하자
// Correct
this.setState((state, props) => ({
counter: state.counter + props.increment
}));
3. state 업데이트는 병합됨
- 변수 독립적으로 업데이트 가능
constructor(props) {
super(props);
this.state = {
posts: [], // 변수 1
comments: [] // 변수 2
};
}
- posts 변수와 comments 변수를 갖는 state 객체
componentDidMount() {
fetchPosts().then(response => {
this.setState({
posts: response.posts // 변수 1의 값 업데이트
});
});
fetchComments().then(response => {
this.setState({
comments: response.comments // 변수 2의 값 업데이트
});
});
}
- 독립적으로 업데이트 했으나 결국 한 state로 병합됨