라이프사이클 단계

리액트 생명주기는 크게 3단계로 나눌 수 있습니다.
Mounting → Updating → Unmounting
각 생명주기에는 순차적으로 실행되는 메서드들이 있습니다.
각 생명주기 마다 메서드의 순서대로 상세설명을 진행하겠습니다.
Mounting
DOM에 Node를 추가하는(컴포넌트가 화면에 나타는) 작업입니다.
메서드는 다음과 같은 순으로 진행됩니다.
constructor → getDerivedStateFromProps → render → componentDidMount
1. constructor(생성자)
- 리액트에서 생성자는 컴포넌트가 생성될 때(DOM에 추가되기 전) 실행됩니다.
- 초기 상태(state)를 설정합니다.
2. getDerivedStateFromProps
- React 17부터 사용합니다(componentWillReciveProps 대체).
- 컴포넌트가 마운트될때 한번 호출됩니다.
*업데이팅 단계에서는 nextProps.value와 prevState.value를 비교 후 변경되었으면 호출됩니다. - props에 의존하는 state를 쓰고 싶은(props를 그대로 state로 쓰고싶은) 경우 사용합니다.
*일반적으로는 props와 state를 명확하게 분리하여 사용하는 것이 좋습니다. - getDerivedStateFromProps의 return값이 해당 컴포넌트의 this.state에 저장됩니다.
// 클래스형 컴포넌트
class MyComponent extends React.Component {
// 마운트 시: componentDidMount처럼 한번만 호출됩니다.
// 업데이팅 시: nextProps.value !== prevState.value 일때만 호출됩니다.
static getDerivedStateFromProps(nextProps) {
return {
**derivedValue**: nextProps.value
};
}
render() {
<div>{this.state.**derivedValue**}</div>
}
}
// 함수형 컴포넌트 사용시 동일한 기능 구현 하려면
function MyComponent({value}) {
const [**derivedValue**, setDerivedValue] = useState(null);
useEffect(() => {
setDerivedValue(value);
}, [value]);
return <div>{**derivedValue**}</div>;
}
3. render
- 순수하게 컴포넌트의 UI 표현을 반환하는 역할을 수행해야 합니다
- 1) 외부 상태 변경이나 부작용을 일으키는 작업은 2) 다른 메서드에서 처리되어야 합니다
*1) setState, 비동기 처리 등
*2) render가 아닌 다른 life-cycle 메서드, 이벤트 핸들러 등
4. componentDidMount
- 컴포넌트가 처음으로 화면에 마운트된 후에 실행되며, 이후에는 다시 호출되지 않습니다.
- 주로 초기 데이터 로딩, 외부 API 호출, 이벤트 리스너 등록 등의 작업을 수행합니다.
Updating
컴포넌트의 상태(state)나 속성(props)이 변경되었을 때 발생합니다.
메서드는 다음과 같은 순으로 진행됩니다.
getDerivedStateFromProps → shouldComponentUpdate → render → componentDidUpdate
1. getDerivedStateFromProps
- nextProps.value와 prevState.value를 비교 후 변경되었으면 호출됩니다.
- 나머지 내용은 마운팅 단계 와 동일합니다.
2. shouldComponentUpdate
- 현재 상태(state)와 현재 속성(props)이 변경되었을 때 컴포넌트 리렌더링 여부를 결정할 수 있습니다.
*리렌더링 여부를 결정한다는 것은, 리렌더링 시킬수도, 안시킬 수도 있다는 것입니다.
예를들면, 특정 state와 props가 변했을 때만 리렌더링 시킬 수 있습니다.
// 클래스형 컴포넌트
class MyComponent extends React.Component {
shouldComponentUpdate(nextProps, nextState) {
// true 리턴: value 속성이 변경되지 않았으므로 리렌더링 수행 X
// false 리턴: value 속성이 변경되었으므로 리렌더링 수행 O
return prevProps.value === nextProps.value;
render() {
// 렌더링 로직
}
}
// 함수형 컴포넌트 사용시 동일한 기능 구현 하려면
const MyComponent = React.memo((props) => {
// 컴포넌트 로직
return (
// JSX
);
}, (prevProps, nextProps) => {
return prevProps.value === nextProps.value;
});
3. render
- 호출되는 상황은 다음과 같습니다.
- 컴포넌트의 props 또는 state가 변경되었을 때
- shouldComponentUpdate 메서드가 true를 반환했을 때
- getDerivedStateFromProps 메서드가 조건에 따라 호출된 후
- 나머지 내용은 마운팅 단계 와 동일합니다.
4. componentDidUpdate
- 컴포넌트의 업데이트가 완료된 후에 호출됩니다.
- componentDidUpdate는 최초 렌더링 시에는 호출되지 않습니다.
- 이전의 속성(props)과 상태(state)에 접근할 수 있습니다.
- 업데이트 전후의 차이를 비교하거나, 추가적인 동작을 수행할 수 있습니다.
// 클래스형 컴포넌트
componentDidUpdate(prevProps, prevState) {
// props.value 변경여부 확인
if (prevProps.value !== this.props.value) {
const element = document.getElementById('myElement');
element.style.transform = 'scale(1.2)';
}
}
// 함수형 컴포넌트 사용시 동일한 기능 구현 하려면
function MyComponent(props) {
// useRef는 리렌더 되어도 값을 유지하므로 prevValue로 사용할 수 있습니다.
const prevValueRef = useRef(props.value);
useEffect(() => {
if (prevValueRef.current !== props.value) {
const element = document.getElementById('myElement');
element.style.transform = 'scale(1.2)';
}
// 이전 props를 현재 props로 업데이트합니다.
prevValueRef.current = props.value;
}, [props.value]);
return (
// JSX
);
}
Unmount
컴포넌트가 DOM에서 제거되는 단계입니다.
메서드는 componentWillUnmount 하나입니다.
1. componentWillUnmount
- 더 이상 필요하지 않은 모든 정리 작업을 수행하는 데 사용합니다.
// 클래스형 컴포넌트
class MyComponent extends React.Component {
componentDidMount() {
this.intervalId = setInterval(
()=> console.log('1초마다 출력'), 1000
);
}
componentWillUnmount() {
clearInterval(this.intervalId);
}
render() {
// 렌더링 로직
}
}
//
function MyComponent() {
useEffect(() => {
const intervalId = setInterval(() => console.log('1초마다 출력'), 1000);
return () => {
clearInterval(intervalId); // unmount
};
}, []);
return (
// JSX
);
[참고자료]
'React' 카테고리의 다른 글
| React 18 주요 변경점 (0) | 2024.04.15 |
|---|---|
| 검색 기능 구현 시 고려사항(API 호출 시점, debouncing) (0) | 2024.04.15 |
| Redux → SWR(2): SWR로 Redux 대체 가능한가? (0) | 2024.04.13 |
| Redux → SWR(1): Redux의 한계 (1) | 2024.04.13 |
| Flux 아키텍쳐 (0) | 2024.04.11 |