Today I Learned ... react.js
🙋♂️ React.js Lecture
🙋 My Dev Blog
React Lecture CH 5
1 - 라이프사이클
2 - setInterval과 라이프사이클 연동
3 - 가위바위보 게임
4 - 고차함수 (Higher-order Func)
5 - useEffect
6 - 클래스 vs Hooks 라이프사이클 비교
import React, { Component } from React;
class RSP extends Component {
state = {
result: '',
score: 0,
imgCoord: 0
};
render() {
const { result, score, imgCoord } = this.state;
return (
<>
<div id="computer" style={{ background: `url(https://en.pimg.jp/023/182/267/1/23182267.jpg) ${imgCoord} 0` }} />
<div>
<button id="rock" className="btn" onClick={onClickBtn('바위')}>바위</button>
<button id="scissor" className="btn" onClick={onClickBtn('가위')}>가위</button>
<button id="paper" className="btn" onClick={onClickBtn('보')}>보</button>
</div>
<div>{result}</div>
<div>현재 {score}점</div>
</>
);
}
}
위 div#computer의 background 이미지를 줘서
가위/바위/보 이미지가 차례로 나오도록 한다.
📌 이미지 스프라이트 (image sprite)
- 여러개의 이미지가 포함된 하나의 이미지.
- 사용할때는 일부만 추출.
(background-position 속성으로)
가위바위보 게임이 처음 렌더링 되자마자 실행되도록 하려고 한다.
🔻
lifeCycle method인 componentDidMount()
를 사용하자.
-> 첫 렌더링시에만 실행된다. (리렌더링시 실행되지 ❌)
참고 - 지난번에 배운 lifeCycle Method
shouldComponentUpdate
-> 리렌더링 여부 결정 (true/false)
componentDidMount | componentWillUnmount |
---|---|
컴포넌트가 첫 렌더링 된 후. 주로 비동기 요청을 함. | 컴포넌트가 제거되기 직전. (부모컴포넌트가 자신을 없앴을 때) 비동기 요청 정리. |
예>
컴포넌트가 제거되었지만, setInterval() 즉 비동기요청은 제거되지 않음.
-> componentWillUnmount()에서 제거해야함.
componentDidMount() {
setInterval(() => {
console.log('hello');
}, 1000);
}
componentWillUnmount() {
// 여기서 clearInterval() 해줘야함.
}
EX>
class RSP extends Component {
state = {
result: '',
score: 0,
imgCoord: 0
};
interval;
componentDidMount() {
this.interval = setInterval(() => {
console.log('hello')
}, 1000);
}
componentWillUnmount() {
clearInterval(this.interval); // 비동기 동작 정리함
}
RSP.jsx
import React, { Component } from 'react';
const rspCoords = {
가위: '0',
바위: '-142px',
보: '-284px',
};
const scores = {
이김: 1,
비김: 0,
짐: -1,
};
class RSP extends Component {
state = {
result: '',
score: 0,
imgCoord: '0',
};
interval;
componentDidMount() {
this.interval = setInterval(() => {
const { imgCoord } = this.state;
if (imgCoord === rspCoords.바위) {
this.setState({
imgCoord: rspCoords.가위,
});
} else if (imgCoord === rspCoords.가위) {
this.setState({
imgCoord: rspCoords.보,
});
} else if (imgCoord === rspCoords.보) {
this.setState({
imgCoord: rspCoords.바위,
});
}
}, 1000);
}
onClickBtn = (choice) => {};
render() {
const { result, score, imgCoord } = this.state;
return (
<>
<div
id="computer"
style={{
background: `url(https://en.pimg.jp/023/182/267/1/23182267.jpg) ${imgCoord} 0`,
}}
/>
<div>
<button id="rock" className="btn" onClick={this.onClickBtn('바위')}>
바위
</button>
<button
id="scissor"
className="btn"
onClick={this.onClickBtn('가위')}
>
가위
</button>
<button id="paper" className="btn" onClick={this.onClickBtn('보')}>
보
</button>
</div>
<div>{result}</div>
<div>현재 {score}점</div>
</>
);
}
}
export default RSP;
주의
- 비동기 함수 바깥의 변수를 참조시 클로저가 발생한다!
(클로저란, 외부 함수보다 중첩 함수의 생존 시간이 긴 경우)
componentDidMount() {
this.interval = setInterval(() => {
const { imgCoord } = this.state; // 👈 이부분을 setInterval()의 콜백 안에 넣어줘야함!!!
if (imgCoord === rspCoords.바위) {
this.setState({
imgCoord: rspCoords.가위,
});
componentWillUnmount() {
clearInterval(this.interval);
}