7장 컴포넌트의 라이프사이클 메서드


모든 컴포넌트에는 라이프사이클(수명 주기)가 존재함. 페이지에 렌더링되기 전인 준비과정에서 시작해서 페이지에서 사라질 때 끝난다.
이 라이프사이클 과정에서 어떤 작업을 수행할 지 메서드화 한다.
라이프사이클 메서드는 클래스형 컴포넌트에서만 사용할 수 있다.

라이프사이클 메서드의 이해

라이프사이클 메서드의 종류는 9가지이다.

마운트

DOM이 생성되고 웹 브라우저 상에 나타나는 것을 마운트라고 한다. 이떄, 호출하는 메서드는 다음과 같다.
Attachments/Picture/Pasted image 20231128214926.png|500

업데이트

컴포넌트가 업데이트되는 4가지 경우

  1. props가 바뀔 때
  2. state가 바뀔 때
  3. 부모 컴포넌트가 리렌더링될 때
  4. this.forceUpdate로 강제로 렌더링 트리거 될 때
    Attachments/Picture/Pasted image 20231128214945.png|500

언마운트

컴포넌트를 DOM 에서 제거하는 것을 언마운트라고 한다.

Untitled

라이프사이클 메서드

render() 함수

constructor 메서드

그냥 생성자 메서드. 컴포넌트 만들 때 실행되겠지 뭐.
constructor 안에서 state 정의 보통

getDerivedStateFromProps 메서드

static getDerivedStateFromProps(nextProps, prevState) {
    if(nextProps.value != = prevState.value) { // 조건에 따라 특정 값 동기화
      return { value: nextProps.value };
    }
    return null; // state를 변경할 필요가 없다면 null을 반환
}

componentDidMount 메서드

componentDidMount() { ... }

shouldComponentUpdate

shouldComponentUpdate(nextProps, nextState) { ... }

getSanpshotBeforeUpdate 메서드

getSnapshotBeforeUpdate(prevProps, prevState) {
    if(prevState.array != = this.state.array) {
    const { scrollTop, scrollHeight } = this.list
      return { scrollTop, scrollHeight };
    }
}

componentDidUpdate 메서드

componentDidUpdate(prevProps, prevState, snapshot) { ... }

componentWilllUnmount 메서드

componentDidCatch 메서드

componentDidCatch(error, info) {
  this.setState({
      error: true
  });
  console.log({ error, info });
}

예제

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>
    );
  }
}
class LifeCycleSample extends Component {
  state = {
    number: 0,
    color: null,
  };
  myRef = null;
  constructor(props) {
    super(props);
    console.log("constructor");
  }
  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);
    return nextProps.number % 10 != 4;
  }

  componentWillUnmount() {
    console.log("componentWillUnmount");
  }

  handleClick = () => {
    this.setState({
      number: this.state.number + 1,
    });
  };

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

에러잡기

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

정리

Attachments/Picture/Pasted image 20231128215016.png