리액트 lifecycle 생명주기

이수연·2022년 12월 21일
0

리액트

목록 보기
4/7

componentDidMount

이 api는 컴포넌트가 화면에 나타날때 호출됩니다. 주로 Dom을 사용해야되는 외부 라이브러리를 사용하거나, 해당 컴포넌트에서 필요로 하는 데이터를 요청하기 위해 axios,fetch등을 이용하여 ajax요청을 하거나, Dom의 속성을 읽거나 직접 변경하는 작업을 진행합니다.

클래스형 컴포넌트를 사용시 componentDidMount() 함수를 호출하면되지만, 함수형 컴포넌트를 사용할경우 useEffect를 사용해 줘야됩니다. 그렇다면 실제로 어떻게 사용하고 차이가 어떻게 다른지 아래 예시코드를 통하여 비교해 보아요!

    componentDidMount() {
        console.log('componentDidMount[Class]');
    }
    useEffect(() => {
        console.log('componentDidMount[Function]');
    }, []);

//useEffect함수를 마운트되고 한번만 실행하게 하려면 두번째 인자로 빈 배열을 넣어주세요 그렇지 않으면 state값이 업데이트 될경우 다시 한번 렌더링을 해줍니다.

static getDerivedStateFromProps()

이 api는 props에서 받아온 값을 state로 동기화 해줘야될때 사용됩니다.

static getDerivedStateFromProps(nextProps, prevState) {
  // 여기서는 setState 를 하는 것이 아니라
  // 특정 props 가 바뀔 때 설정하고 설정하고 싶은 state 값을 리턴하는 형태로
  // 사용됩니다.
  /*
  if (nextProps.value !== prevState.value) {
    return { value: nextProps.value };
  }
  return null; // null 을 리턴하면 따로 업데이트 할 것은 없다라는 의미
  */
}

shouldComponentUpdate

리액트는 virtual dom을 사용하기 때문에 변화가 있는부분만 바꿔서 렌더링을 합니다.
따라서 속도가 굉장히 빠른데요. 하지만 부모 컴포넌트가 리렌더링이 될경우, 자식컴포넌트들도 렌더링이 됩니다. 이작업은 그렇게 부하가 많은 작업은 아니지만 , 컴포넌트가 무수히 많이 렌더링이 될경우 cpu자원낭비를 야기 할수있기때문에 이 api를 사용합니다. 이함수의 기본 세팅은 true를 반환하는데 사용자의 설정에 따라 false를 반환한다면 render 함수를 호출하지 않습니다.

//class 버전

 shouldComponentUpdate(nextProps){
    return nextProps.value !== this.props.value;
  }

//hook 버전

React.memo(function MyComponent (props) {

  return <div>{ "My Component " + props.value }</div>;

}) 

간단히 말해 최적화할 컴포넌트를 저장해 두었다가 해당컴포넌트에서 이벤트가 발생될때만
렌더링 하게끔 하는 고마운 api다!

getSnapshotBeforeUpdate()

getSnapshotBeforeUpdate 는 컴포넌트에 변화가 일어나기 직전의 DOM 상태를 가져와서 특정 값을 반환하면 그 다음 발생하게 되는 componentDidUpdate 함수에서 받아와서 사용을 할 수 있습니다. 그렇다면 왜 사용할까요? 업데이트 되기 전에 props와state를 미리 확보하는게 목적입니다. 이 api에서 미리 props와 state를 확보한후 componentDidUpdate에서 이를 받는것 입니다. 중요한 점은 getSnapshotBeforeUpdate의 반환값이 componentDidUpdate의 세번째 인자로 들어간다는 것입니다. componentDidUpdate를 사용하기위한 필요한 api 입니다.

  getSnapshotBeforeUpdate(prevProps, prevState) {
    // DOM 업데이트가 일어나기 직전의 시점입니다.
    // 새 데이터가 상단에 추가되어도 스크롤바를 유지해보겠습니다.
    // scrollHeight 는 전 후를 비교해서 스크롤 위치를 설정하기 위함이고,
    // scrollTop 은, 이 기능이 크롬에 이미 구현이 되어있는데, 
    // 이미 구현이 되어있다면 처리하지 않도록 하기 위함입니다.
    if (prevState.array !== this.state.array) {
      const {
        scrollTop, scrollHeight
      } = this.list;

      // 여기서 반환 하는 값은 componentDidMount 에서 snapshot 값으로 받아올 수 있습니다.
      return {
        scrollTop, scrollHeight
      };
    }
  }

이 api는 아직 해당하는 hook이 없다고 합니다.

componentDidUpdate

이 api는 컴포넌트에서 reder를 호출하고 나서 발생하게 됩니다. 따라서 props의 값과 state값을 이미 받았기 때문에 변경이 된후 입니다. 그리고 파라미터를 통해 이전의 값인 prevProps 와 prevState 를 조회 할 수 있습니다. 그리고, getSnapshotBeforeUpdate 에서 반환한 snapshot 값은 세번째 값으로 받아옵니다.

componentDidUpdate(prevProps, prevState, snapshot) {

}

이 api도 useEffect hook을 통하여 구현이 가능합니다. 아래와 같이 count의 값이 변경될때만 useEffect안의 함수가 호출되기때문에 componentDidUpdate와 동일하게 표현 가능합니다.

  useEffect(() => {
    // 컴포넌트가 업데이트 되고 setTimeout함수를 실행합니다.
    setTimeout(() => {
    	document.title = `You clicked ${count} times`;
    }, 3000);   
  }, [count]);

componentWillUnmount

컴포넌트가 더이상 필요하지 않게 된다면 단하나의 api가 호출됩니다.
주로 등록했었던 이벤트를 제거하고, 만약에 setTimeout 을 걸은것이 있다면 clearTimeout 을 통하여 제거를 합니다. 추가적으로, 외부 라이브러리를 사용한게 있고 해당 라이브러리에 dispose 기능이 있다면 여기서 호출해주시면 됩니다.

componentWillUnmount() {
  // 이벤트, setTimeout, 외부 라이브러리 인스턴스 제거
}

이 api 또한 useEffect로 구현이 가능합니다. 바로 스크롤 이벤트를 구현할때 입니다!

  useEffect(() => {
    // scroll 이벤트를 만들어줍니다. 스크롤을 움직일때 마다 
    // onScroll 함수가 실행됩니다.
    window.addEventListener("scroll", onScroll);
    return () => window.removeEventListener("scroll", onScroll); <---- 집중 !!!
  }, []);
  return state;
};

스크롤 이벤트는 스크롤을 내릴때마다 이벤트가 일어나기때문에 얘기치 못한 상황이 발생할수 있습니다. 이를 방지하기 위하여 스크롤 이벤트가 끝났을경우 꼭 이벤트를 삭제 해주어야됩니다. 이럴때 useEffect로 위와같이 구현하면 componentWillUnmount() api를 사용하는것과 동일하게 구현 가능합니다.

0개의 댓글