모든 리액트 컴포넌트에는 라이프사이클(수명 주기)이 존재합니다. 컴포넌트의 수명은 페이지에 렌더링되기 전인 준비 과정에서 시작하여 페이지에서 사라질 때 끝납니다.
리액트 프로젝트를 진행하다 보면 가끔 컴포넌트를 처음으로 렌더링할 때 어떤 작업을 처리해야하거나 컴포넌트를 업데이트하기 전후로 어떤 작업을 처리해야 할 수도 있고, 또 불필요한 업데이트를 방지해야 할 수도 있습니다.
이때는 컴포넌트의 라이프사이클 메서드를 사용합니다. 참고로 라이프사이클 메서드는 클래스형 컴포넌트에서만 사용할 수 있습니다. 함수 컴포넌트에서는 사용할 수 없는데요. 그 대신에 Hooks 기능을 사용하여 비슷한 작업을 처리할 수 있습니다.
라이프사이클 메서드의 종류는 총 아홉 가지입니다. Will 접두사가 붙은 메서드는 어떤 작업을 작동하기 전에 실행되는 메서드이고, Did 접두사가 붙은 메서드는 어떤 작업을 작동한 후에 실행되는 메서드입니다.
이 메서드들은 우리가 컴포넌트 클래스에서 덮어 써 선언함으로써 사용할 수 있습니다.
라이프사이클은 총 세 가지, 마운트, 업데이트, 언마운트 카테고리로 나눕니다.
출처: http://projects.wojtekmaj.pl/react-lifecycle-methods-diagram/
DOM이 생성되고 웹 브라우저상에 나타나는 것을 마운트(Mount)라고 합니다. 이때 호출하는 메서드는 다음과 같습니다.
Mount → constructor → getDerivedStateFromProps → render → componentDidMount
// Class
class Example extends React.Component {
constructor(props) {
super(props);
this.state = { count: 0 };
}
// Hooks
const Example = () => {
const [count,setCount] = useState(0);
}
// Class
class Example extends React.Component {
static getDerivedStateFromProps(nextProps, prevState) {
if (nextProps.value !== prevState.value) {
return { value: nextProps.value }
}
return null
}
}
// Class
class Example extends React.Component {
render() {
return <div>컴포넌트</div>
}
}
// Hooks
const example = () => {
return <div>컴포넌트</div>
}
// Class
class Example extends React.Component {
componentDidMount() {
...
}
}
// Hooks
const Example = () => {
useEffect(() => {
...
}, []);
}
컴포넌트는 다음과 같은 총 네 가지 경우에 업데이트 합니다.
이렇게 컴포넌트를 업데이트할 때는 다음 메서드를 호출합니다.
출처: https://thebook.io/080203/ch07/01-02/
컴포넌트는 다양한 이유로 업데이트 될 수 있습니다. 첫째, 부모 컴포넌트에서 넘겨주는 props가 바뀔 때 입니다. 컴포넌트에 전달하는 props의 값이 바뀌면 컴포넌트 렌더링이 이루어집니다. 둘째, 컴포넌트 자신이 들고 있는 state가 setState를 통해 업데이트 될 때입니다. 셋째, 부모 컴포넌트가 리렌더링될 때 입니다. 자신에게 할당된 props가 바뀌지 않아도, 또는 자신이 들고 있는 state가 바뀌지 않아도, 부모 컴포넌트가 리렌더링되면 자식 컴포넌트 또한 리렌더링됩니다.
getDerivedStateFromProps: 이 메서드는 마운트 과정에서도 호출되며, 업데이트가 시작하기 전에도 호출됩니다. props의 변화에 따라 state 값에도 변화를 주고 싶을 때 사용합니다.
shouldComponentUpdate: 컴포넌트가 리렌더링을 해야 할지 말아야 할지를 결정하는 메서드입니다. 이 메서드에서는 true 혹은 false 값을 반환해야 하며, true를 반환하면 다음 라이프사이클 메서드를 계속 실행하고, false를 반환하면 작업을 중지합니다. 즉, 컴포넌트가 리렌더링되지 않습니다. 만약 특정 함수에서 this.forceupdate() 함수를 호출한다면 이 과정을 생략하고 바로 render 함수를 호출합니다.
// Class
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
}
)
render: 컴포넌트를 리렌더링합니다.
getSnapshotBeforeUpdate: 컴포넌트 변화를 DOM에 반영하기 바로 직전에 호출하는 메서드입니다.
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
}
}
// Class
class Example extends React.Component {
componentDidUpdate(prevProps, prevState) {
...
}
}
// Hooks
const Example = () => {
useEffect(() => {
...
});
}
마운트의 반대 과정, 즉 컴포넌트를 DOM에서 제거하는 것을 언마운트(Unmount)라고 합니다.
출처: https://thebook.io/080203/ch07/01-04/
// Class
class Example extends React.Component {
coomponentWillUnmount() {
...
}
}
// Hooks
const Example = () => {
useEffect(() => {
return () => {
...
}
}, []);
}
reference
https://ko.reactjs.org/docs/react-component.html
리액트를 다루는 기술
https://thebook.io/080203/
https://kyun2da.dev/react/%EB%A6%AC%EC%95%A1%ED%8A%B8-%EB%9D%BC%EC%9D%B4%ED%94%84%EC%82%AC%EC%9D%B4%ED%81%B4%EC%9D%98-%EC%9D%B4%ED%95%B4/