React Lifecycle methods

shorry·2022년 6월 16일
0

React

목록 보기
2/2

📌라이프사이클의 분류


  • 리액트는 컴포넌트 기반의 View를 중심으로 한 라이브러리다.
  • 각각의 컴포넌트에는 라이프사이클 즉, 컴포넌트의 수명주기가 존재한다.
  • 수명은 보통 페이지에서 렌더링되기 전인 준비과정에서 시작하여 페이지에서 사라질 때 끝난다.
  • 라이프 사이클은 위의 그림과 같이 총 9가지, 유형은 크게 3가지가 존재한다.
    • 마운트 : DOM이 생성되고 웹 브라우저 상에서 나타나는 것
    • 언마운트 : DOM에서 제거되는 것
    • 업데이트 : 다음과같은 4가지 상황에서 발생한다
      • props가 바뀔 때
      • state가 바뀔 때
      • 부모 컴포넌트가 리렌더링 될 때
      • this.forceUpdate로 강제로 렌더링을 트리거할 때

📌라이프 사이클 메서드 살펴보기


1. constructor


  • 컴포넌트를 만들 대 처음으로 실행된다.
  • 초기 state 를 정할 수 있다.
  • super(props) 를 하는 이유는, 원래 React.Component가 지니고 있는 constructor가 존재하기 때문에, 우선 호출해야한다.
  • 함수형 - useState hook을 사용하여 설정해줄 수 있다.
// Class
class Example extends React.Component {
    constructor(props) {
        super(props);
        this.state = { count: 0 };
}

// Hooks
const Example = () => {
    const [count,setCount] = useState(0);
}

2. getDerivedStateFromProps


  • 리엑트 16.3버전 이후에 생긴 메서드
  • props로 받아 온 값을 state에 동기화 시키는 용도로 사용한다.
  • 컴포넌트가 마운트될 때와 업데이트 될 때 호출 된다.
  • 예를 들어, 무엇을 움직이도록 만들지 결정하기 위하여 이전과 현재의 자식 엘리먼트를 비교하는 <Transition>과 같은 컴포넌트를 구현할 때에 편리하게 사용할 수 있다.
  • 함수형 - 이 기능을 대체할만한 hook이 없다.
class Example extends React.Component {
  static getDerivedStateFromProps(nextProps, prevState) {
    if (nextProps.value !== prevState.value) {
      return { value: nextProps.value }
    }
    return null
  }
}

3. shouldComponentUpdate


  • props나 state를 변경했을 때, 리렌더링을 할지 말지 결정하는 메서드.
  • 반드시 true나 false를 반환해야한다.
  • 성능 최적화만을 위한 것이다.
  • 클래스형은 보통은 PureComponent 를 추천한다.
  • 함수형 - porps는 React.memo를 state는 useMemo를 활용하여 성능을 개선할 수 있다.
class Example extends React.Component {
  shouldComponentUpdate(nextProps) {
    return nextProps.value !== this.props.value
  }
}

// Hooks
const Example = React.memo(() => {
      ...
  },
  (prevProps, nextProps) => {
    return nextProps.value === prevProps.value
  }
)

4. render


  • 가장 기초적이면서도 가장 중요한 메서드 이기도 하다.
  • 컴포넌트를 렌더링할 때 필요한 메서드.
  • 유일한 필수 메서드
  • 함수형 - 별다른 명령어 없이 컴포넌트를 렌더링 할 수 있다.
// Class
class Example extends React.Component {
  render() {
    return <div>컴포넌트</div>
  }
}

// Hooks
const example = () => {
  return <div>컴포넌트</div>
}

5. getSnapshotBeforeUpdate


  • render에서 만들어진 결과가 브라우저에 실제로 반영되기 직전에 호출된다.
  • 가장 마지막으로 렌더링된 결과가 DOM 등에 반영되기 전에 호출된다.
  • 채팅 화면처럼 스크롤 위치를 따로 처리하는 작업이 필요한 UI 등을 생각해볼 수 있다.
  • 이 메서드를 사용하면 컴포넌트가 DOM으로부터 스크롤 위치 등과 같은 정보를 이후 변경되기 전에 얻을 수 있다.
  • 이 생명주기 메서드가 반환하는 값은 componentDidUpdate() 에 세번째 인자로 전달된다.
  • 함수형 - 이 기능을 대체할만한 hook이 없다.
class Example extends React.Component {
  getSnapshotBeforeUpdate(prevProps, prevState) {
    if (prevProps.list.length < this.props.list.length) {
      const list = this.listRef.current
      return list.scrollHeight - list.scrollTop
    }
    return null
  }
}

6. componentDidMount


  • 이 메서드는 컴포넌트를 만들고 첫 렌더링을 마친 후 실행.
  • 외부API를 호출하거나, 브라우저에 나타난 DOM에 직접 접근이 가능하므로 특정 DOM에 event를 걸어줄 수도 있다.
  • 함수형 - useEffect hook 을 사용한다.
  • useEffect의 deps를 비워줘야지만 똑같은 메소드를 구현할 수 있다.
class Example extends React.Component {
    componentDidMount() {
        ...
    }
}

// Hooks
const Example = () => {
    useEffect(() => {
        ...
    }, []);
}

7. componentDidUpdate


  • 이것은 리렌더링을 완료한 후 실행한다.
  • 업데이트가 끝난 직후이므로, DOM관련 처리를 해도 무방하다.
  • getSnapshotBeforeUpdate() 에서 반환하는 값을 3번째 인자로 받는다.
  • 함수형 - useEffect hook 을 사용한다.
// Class
class Example extends React.Component {
    componentDidUpdate(prevProps, prevState) {
        ...
    }
}

// Hooks
const Example = () => {
    useEffect(() => {
        ...
    });
}

8. componentWillUnmount


  • 이 메서드는 컴포넌트를 DOM에서 제거할 때 실행한다.
  • componentDidMount에서 등록한 이벤트가 있다면 여기서 제거 작업을 해야한다.
  • 함수형 - useEffect의 CleanUp 함수를 통해 구현이 가능하다.
// Class
class Example extends React.Component {
    coomponentWillUnmount() {
        ...
    }
}

// Hooks
const Example = () => {
    useEffect(() => {
        return () => {
            ...
        }
    }, []);
}

9. componentDidCatch


  • 마지막으로 맨 위의 사진에는 보이지 않지만 componentDidCatch라는 메서드가 존재한다.
  • 이 메서드는 컴포넌트 렌더링 도중에 에러가 발생 했을 때 애플리케이션이 멈추지 않고 오류 UI를 보여줄 수 있게 해준다.
  • 함수형 - 이 기능을 대체할만한 hook이 없다.
class Example extends React.Component {
  componentDidCatch(error, info) {
    console.log('에러가 발생했습니다.')
  }
}

📌Hook에서 사용못하는 Lifecycle method들은??


  • 우리의 목표는 Hook이 class의 모든 사용 사례를 가능한 한 빨리 커버하게 하는 것입니다. 드문 getSnapshotBeforeUpdategetDerivedStateFromError 및 componentDidCatch 생명주기에 해당하는 Hook은 아직 없지만, 곧 추가할 계획이다. (리액트공식문서 참고)

📌react의 setState (hook에서는 useState)를 왜 사용하는지


  • 불변성(immutable)을 유지해야 한다.
  • 리액트가 웹 상에 렌더링 되기 위해선 render() 메서드가 실행되어야한다. ( 위에 공부 내용을 참고하면, state가 변경될 때 업데이트 사이클이 실행이되고, 그 때 shouldComponentUpdate 가 true이면 render() 함수가 실행이된다는걸 알 수 있다. )
  • 값이 변경 되었다는걸 판단하기 위해 리액트는 객체로 저장된 state를 비교 연산을 하는데, 객체는 참조에 의한 전달을 한다.
  • 그러므로 새로운 주소값에 할당된 새로운 객체를 만들어주는 setState나 useState 를 사용해야한다.
  • 추가적인 사항
    • setState는 비동기적으로 동작하기 때문에 state가 직접 수정되어 여러번 상태를 업데이트 하는 경우, 이전 업데이트 내용이 다음 업데이트 내용에 덮어 쓰여질 수가 있다. 즉, 예상치 못한 곳에서 버그가 발생 할 수 있다.
    • PureComponent에서 동작하지 않는다. PureComponent는 this.state와 setState를 비교해 업데이트가 필요한 경우에만 render함수를 호출해 준다. 이때, state를 직접 수정하게되면 기존의 this.state와 setState가 동일하므로 리액트는 render함수를 호출하지 않는다.


📌Reference


profile
I'm SHORRY about that

2개의 댓글

comment-user-thumbnail
2022년 6월 19일

good...!

1개의 답글