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);
  }