[React] 라이프 사이클 메서드(class형, Hooks useEffect())
※배워가고 있는 학생입니다. 틀린 부분이 있다면 댓글로 피드백 부탁드립니다.
1) 컴포넌트의 라이프사이클(수명주기)
모든 리액트 컴포넌트에는 라이프사이클(수명 주기)이 존재한다.
컴포넌트의 수명은 페이지에 렌더링되기 전인 준비 과정에서 시작하여 페이지에서 사라질 때 끝난다.
리액트 프로젝트를 진행하다 보면 가끔 컴포넌트를 처음으로 렌더링할 때 어떤 작업을 처리해야 하거나 컴포넌트를 업데이트하기 전후로 어떤 작업을 처리해야 할 수도 있고, 또 불필요한 업데이트를 방지해야 할 수도 있다.
이때 컴포넌트의 라이프사이클 메서드를 오버라이딩하여 특정 시점에 코드가 실행되도록 설정할 수 있다.
라이프사이클 메서드는 클래스형 컴포넌트에서만 사용할 수 있으나, 함수형 컴포넌트에서는 사용할 수 없는데, Hooks 기능을 사용하여 비슷한 작업을 처리할 수 있다.
라이프사이클은 총 세 가지, 즉 마운트, 업데이트, 언마운트 카테고리로 나눈다.
마운트(mount)
: DOM이 생성되고 웹 브라우저상에 나타나는 것
• constructor: 컴포넌트를 새로 만들 때마다 호출되는 클래스 생성자 메서드
• getDerivedStateFromProps: props에 있는 값을 state에 넣을 때 사용하는 메서드
• render: 우리가 준비한 UI를 렌더링하는 메서드
• componentDidMount: 컴포넌트가 웹 브라우저상에 나타난 후 호출하는 메서드
업데이트(update)
컴포넌트를 업데이트 하는 경우:
1. props가 바뀔 때
2. state가 바뀔 때
3. 부모 컴포넌트가 리렌더링될 때
4. this.forceUpdate로 강제로 렌더링을 트리거할 때
• getDerivedStateFromProps: 마운트 과정에서도 호출되며, 업데이트가 시작하기 전에도 호출됨. props의 변화에 따라 state 값에도 변화를 주고 싶을 때 사용
• shouldComponentUpdate: 컴포넌트가 리렌더링을 해야 할지 말아야 할지를 결정하는 메서드
• render: 컴포넌트를 리렌더링
• getSnapshotBeforeUpdate: 컴포넌트 변화를 DOM에 반영하기 바로 직전에 호출하는 메서드
• componentDidUpdate: 컴포넌트의 업데이트 작업이 끝난 후 호출하는 메서드
언마운트(unmount)
:마운트의 반대 과정, 즉 컴포넌트를 DOM에서 제거하는 것
• componentWillUnmount: 컴포넌트가 웹 브라우저상에서 사라지기 전에 호출하는 메서드
2) 라이프사이클 메서드 - class component
클래스 컴포넌트는 항상 props 로 기본 constructor를 호출해야 한다.
- 마운트: DOM에 렌더링 될 때마다
- 삭제: DOM이 삭제될 때마다
클래스 컴포넌트에서 특정 메서드를 사용해서 컴포넌트가 (언)마운트 될 때, 일부 코드를 작동시킬 수 있다.
이때 사용되는 특정 메서드를 라이프사이클 메서드(생명주기 메서드)라고 부른다.
라이프사이클 메서드는 여러 종류가 있지만, 여기에서는 주요 메서드 몇가지만 다뤄보겠다.
(render, conctructor, componentDidMount, componentDidUpdate, componentWillUnmount)
**Will 접두사가 붙은 메서드: 어떤 작업을 작동하기 전에 실행되는 메서드
**Did 접두사가 붙은 메서드: 어떤 작업을 작동한 후에 실행되는 메서드
💡 render ()
render() { ... }
- 데이터가 변경되어 새 화면을 그려야 할 때 자동으로 호출
- render() 함수가 반환하는 JSX를 화면에 그림
- 라이프사이클 메서드 중 유일한 필수 메서드
- 이 메서드 내에서 this.props와 this.state에 접근 가능하고 리액트 요소를 반환
- 이 메서드 안에서는 이벤트 설정이 아닌 곳에서 setState를 사용하면 안 되며, 브라우저의 DOM에 접근해서도 안됨
(DOM 정보를 가져오거나 state에 변화를 줄 때는 componentDidMount에서 처리해야 함)
💡 construtor
constructor(props) { ... }
- 컴포넌트를 만들 때 처음으로 실행
- 해당 컴포넌트가 "마운트되기 전"에 호출
- 이 메서드에서 초기 state를 정할 수 있음
💡 componentDidMount
componentDidMount() { ... }
- 컴포넌트를 만들고, 첫 렌더링을 다 마친 후 실행
- 컴포넌트가 화면에 모두 표현된 이후 해야 하는 작업들을 여기서 진행
(ex. 다른 자바스크립트 라이브러리 또는 프레임워크의 함수를 호출, 이벤트 등록, setTimeout, setInterval, 네트워크 요청 같은 비동기 작업)
💡 componentDidUpdate
componentDidUpdate(prevProps, prevState, snapshot) { ... }
- 리렌더링을 완료한 후 실행
- 업데이트가 끝난 직후이므로, DOM 관련 처리를 해도 무방
- DOM의 정보를 변경할 때 사용
- 여기서는 prevProps 또는 prevState를 사용하여 컴포넌트가 이전에 가졌던 데이터에 접근할 수 있음
- 부모 컴포넌트로부터 전달된 이전 props 와, 이전 state을 인자로 전달받음
💡 componentWillUnmount
componentWillUnmount() { ... }
- 컴포넌트를 DOM에서 제거할 때 실행
- componentDidMount에서 등록한 이벤트, 타이머, 직접 생성한 DOM이 있다면 여기서 제거 작업을 해야 함
3) useEffect - Hooks
앞서 언급했듯, 라이프사이클 메서드는 클래스 컴포넌트에서만 사용할 수 있다.
하지만 함수형 컴포넌트에서도 Hooks 를 이용해 비슷한 기능을 낼 수 있는데, 그것이 바로 useEffect 함수 이다.
useEffect는 리액트 컴포넌트가 렌더링될 때마다 특정 작업을 수행하도록 설정할 수 있는 Hook으로,
컴포넌트가 mount 됐을 때, unmount 됐을 때, update 됐을 때 특정작업을 수행한다.
- 기본 형태: useEffect(function, deps)
- function: 수행하고자 하는 작업
- deps: 배열 형태이며, 배열 안에는 검사하고자 하는 특정 값 or 빈배열 (업데이트되는 값)
1) 마운트 될 때만 실행하고 싶을 때(컴포넌트가 처음 렌더링될 때)
** life cycle중 componentDidmount처럼 실행
useEffect에서 설정한 함수를 컴포넌트가 화면에 맨 처음 렌더링될 때만 실행하고, 업데이트될 때는 실행하지 않으려면 함수의 두 번째 파라미터로 비어 있는 배열을 넣어 주면 된다.
useEffect(() => {
console.log('마운트될 때만 실행됩니다.');
}, []);
2) 마운트, 특정 값이 업데이트될 때 모두 실행하고 싶을 때
**componentDidUpdate, componentDidmount 둘 모두 실행하는 것과 동일
useEffect를 사용할 때, 특정 값이 변경될 때에도 호출하고 싶을 경우도 있을 것이다.
그 경우에는, useEffect의 두 번째 파라미터로 전달되는 배열 안에 검사하고 싶은 값을 넣어 주면 된다.
검사하고 싶은 값, 즉 업데이트되는 그 '특정 값'을 넣으면 된다.
useEffect(() => {
console.log(name);
}, [name]);
배열 안에는 useState를 통해 관리하고 있는 상태를 넣어 주어도 되고, props로 전달받은 값을 넣어 주어도 된다.
지금 이 경우에는, []안에 들어간 특정 값이 업데이트 될 때에도 호출되고, 마운트될 때에도 호출된다.
**마운트 될 때는 실행 안 하고, 업데이트 될 때만 실행시키고 싶을 때(일종의 꼼수!)
const mounted=useRef(false);
useEffect(()=>{
if(!mounted.current){
mounted.current=true;
}else{
//업데이트 될 때 실행할 내용
}
}, [바뀌는 값]);
mount 될 때 useEffect 부분이 실행되는 것은 막지 못하지만, mount 될 때는 아무 내용도 실행하지 않게 하면 업데이트될 때만 진짜 실행시킬 내용을 실행할 수 있다!
3) 컴포넌트가 unmount 되거나 update 되기 직전 (clean up 함수)
**componentWillUnmount처럼 실행
컴포넌트가 언마운트되기 전이나 업데이트되기 직전에 어떠한 작업을 수행하고 싶다면 useEffect에서 뒷정리(cleanup) 함수를 반환해 주어야 한다.
- 언마운트 될 때만 cleanup 함수 실행하고 싶을 때 - 두번째 파라미터에 빈 배열을 넣는다
- 특정 값이 업데이트 되기 직전에 cleanup 함수를 실행하고 싶을 때 - deps 배열 안에 검사하고 싶은 값을 넣어준다
useEffect(() => {
console.log(‘effect‘);
console.log(name);
return () => {
console.log(‘cleanup‘);
console.log(name);
};
});
❗참고: deps에 특정 값 넣기❗
위에서 본 것처럼, deps 에 특정 값을 넣게 되면 컴포넌트가 처음 마운트 될 때, 특정 값이 바뀔 때, 언마운트 될 떄, 특정 값이 바뀌기 직전에 호출된다.
useEffect 안에서 사용하는 상태나 props가 있다면, useEffect 의 deps 에 넣어주어야 하는 것이 원칙이다.
만약 사용하는 값을 넣어주지 않는다면, useEffect 안의 함수가 실행될 때 최신 상태, props 를 가리키지 않는다.
deps 파라미터를 생략한다면, 컴포넌트가 리렌더링 될 때마다 useEffect 함수가 호출된다.
**리액트 컴포넌트는 기본적으로 부모컴포넌트가 리렌더링되면 자식 컴포넌트 또한 리렌더링이 된다.
바뀐 내용이 없을지라도.
4) 참고자료
- 리액트를 다루는 기술
더북(TheBook): 리액트를 다루는 기술 [개정판]
thebook.io
[React] 5 - Component > 컴포넌트의 생명주기
goalcomponent 생명주기의 모든 것모든 컴포넌트는 여러 종류의 “lifecycle methods”를 가지며, 이 메서드를 오버라이딩하여 특정 시점에 코드가 실행되도록 설정할 수 있다.=> when an instance of a component
velog.io
- 웹 게임을 만들며 배우는 리액트 (zero cho)
https://www.inflearn.com/course/web-game-react/dashboard
[무료] 웹 게임을 만들며 배우는 React - 인프런 | 강의
웹게임을 통해 리액트를 배워봅니다. Class, Hooks를 모두 익히며, Context API와 React Router, 웹팩, 바벨까지 추가로 배웁니다., 8개의 간단한 웹게임을 만들어보며 배우는 리액트 강좌입니다.React Hooks에
www.inflearn.com