개발새발개발/React

React - 라이프사이클 메서드 사용

birdsfoot 2025. 1. 2.

실습 순서

1. LifeCycleSample 컴포넌트 만들기

2. App에 렌더링하기

3. 버튼 누르고 콘솔 창 관리하기

 

 

1. LifeCycleSample 컴포넌트 만들기

// LifeCycleSample.js

import React, { Component } from 'react';

class LifeCycleSample extends Component {
  state = {
    number: 0,
    color: null,
  };

  myRef = null; //ref를 설정할 부분

  // 초기 state 설정
  constructor(props) {
    super(props);
    console.log('constructor');
  }

  // props로 받아온 값을 state에 동기화
  // 부모에게서 받은 color 값을 state에 동기화
  static getDerivedStateFromProps(nextProps, prevState) {
    console.log('getDerivedStateFromProps');
    if (nextProps.color !== prevState.color) {
      return { color: nextProps.color };
    }
    return null;
  }

  // 첫 렌더링 마친 후 실행
  componentDidMount() {
    console.log('componentDidMount');
  }

  // 리렌더링 여부 결정
  shouldComponentUpdate(nextProps, nextState) {
    console.log('shouldComponentUpdate', nextProps, nextState);
    // 숫자의 마지막 자리가 4면 리렌더링 하지 않는다
    return nextState.number % 10 !== 4;
  }

  // 언마운트되기 전
  componentWillUnmount() {
    console.log('componentWillUnmount');
  }

  // 클릭 시 더하기 버튼
  handleClick = () => {
    this.setState({
      number: this.state.number + 1,
    });
  };

  // render 결과물이 브라우저에 반영되기 전
  // DOM에 변화가 일어나기 직전의 색상 속성을 snapshot 값으로 반환
  // componentDidUpdate에서 조회할 수 있게 함
  getSnapshotBeforeUpdate(prevProps, prevState) {
    console.log('getSnapshotBeforeUpdate');
    if (prevProps.color !== this.props.color) {
      return this.myRef.style.color;
    }
    return null;
  }

  // 업데이트가 끝난 직후
  componentDidUpdate(prevProps, prevState, snapshot) {
    console.log('componentDidUpdate', prevProps, prevState);
    if (snapshot) {
      console.log('업데이트 되기 직전 색상 : ', snapshot);
    }
  }

  render() {
    console.log('render');

    const style = {
      color: this.props.color,
    };

    return (
      <div>
        <h1 style={style} ref={(ref) => (this.myRef = ref)}>
          {this.state.number}
        </h1>
        <p>color : {this.state.color}</p>
        <button onClick={this.handleClick}>더하기</button>
      </div>
    );
  }
}

export default LifeCycleSample;

 

  • 라이프사이클 메서드를 실행할 때마다 콘솔창에 출력
  • 부모 컴포넌트로부터 props로 색상을 받아 버튼을 누르면 state.number 값을 1씩 더함

 

 

2. App에 렌더링하기

//App.js

import React, { Component } from 'react';
import LifeCycleSample from './LifeCycleSample';

// 랜덤 색상 생성
// 16777215를 hex로 표현하면 ffffff가 되므로 000000~ffffff 값을 반환함
function getRandomColor() {
  return '#' + Math.floor(Math.random() * 16777215).toString(16);
}

class App extends Component {
  state = {
    color: '#000000',
  };

  handleClick = () => {
    this.setState({
      color: getRandomColor(),
    });
  };

  render() {
    return (
      <div>
        <button onClick={this.handleClick}>랜덤 색상</button>
        <LifeCycleSample color={this.state.color} />
      </div>
    );
  }
}

export default App;

 

 

 

 

 

3. 버튼 누르고 콘솔 창 관리하기

  • console에 2개씩 출력되는 이유 : React Strict  Mode
    • constructor, getDerivedStateFromProps, render, componentDidMount (일부 경우) 메서드를 2번씩 실행
    • 예상치 못한 동작이나 부작용을 감지하고 경고하기 위해 사용(버그 방지 목적)
    • 사용하는걸 권장함
    • 제거 방법
      • index.js에서 StrictMode를 삭제하면 됨
// index.js

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);

 

 

 

 

랜덤 색상 기능

 

 

 

 

 

더하기 기능

  • 4일 땐 업데이트가 중단됨

 

 

 

에러 잡아내기

// ErrorBoundary.js

import React, { Component } from 'react';

class ErrorBoundary extends Component {
  state = {
    error: false,
  };
  componentDidCatch(error, info) {
    this.setState({
      error: true,
    });
    console.log({ error, info });
  }
  render() {
    if (this.state.error) return <div> 에러가 발생했습니다</div>;
    return this.props.children;
  }
}

export default ErrorBoundary;

 

  • error가 발생하면 componentDidCatch 메서드 호출되어 this.state.error 값이 true로 업데이트 됨
  • this.state.error 값이 true이면 render 함수가 에러가 발생했음을 알리는 문구를 렌더링함

 

 

//App.js

import React, { Component } from 'react';
import LifeCycleSample from './LifeCycleSample';
import ErrorBoundary from './ErrorBoundary';

// 랜덤 색상 생성
// 16777215를 hex로 표현하면 ffffff가 되므로 000000~ffffff 값을 반환함
function getRandomColor() {
  return '#' + Math.floor(Math.random() * 16777215).toString(16);
}

class App extends Component {
  state = {
    color: '#000000',
  };

  handleClick = () => {
    this.setState({
      color: getRandomColor(),
    });
  };

  render() {
    return (
      <div>
        <button onClick={this.handleClick}>랜덤 색상</button>
        <ErrorBoundary>
          <LifeCycleSample color={this.state.color} />
        </ErrorBoundary>
      </div>
    );
  }
}

export default App;
  • App.js에서 LifeCycleSample 컴포넌트를 감싸줌

 

 

결과

 

댓글