리액트는 MVC 패턴 중 view에 해당하는 라이브러리이다. 그러다 보니 각각의 컴포넌트는 생명주기인 '라이프 사이클'이 존재한다.
컴포넌트의 수명은 일반적으로 페이지에서 렌더링 되기 전 준비 과정에서 시작해 페이지에서 사라질 때 끝이 난다.
라이프 사이클 유형
이 생명주기는 컴포넌트가 브라우저상에 나타나고, 업데이트되고, 사라지게 될 때 호출되는 메서드들이 있다.
리액트에서는 이러한 것들을 라이프사이클메서드 Mount, Update, Unmount라고 한다.
Mount
는 DOM이 생성되고 웹 브라우저 상에서 나타나는 것을 뜻한다.
Update
는 다음과 같은 상황에서 발생한다.
- props가 바뀔 때
- state가 바뀔 때
- 부모 컴포넌트가 리렌더링 될 때
- 리액트의 클래스 컴포넌트는 라이프 사이클 메서드를 사용하고, 함수형 컴포넌트는 Hook을 사용한다.
사이클 메서드
Constructor
- 컴포넌트가 처음 만들어질 때 실행되는 컴포넌트 생성자 메서드로 컴포넌트가 생성되면 가장 먼저 실행되는 메서드이다. 이 메서드에서 초기 state를 정할 수 있다.
this.props, this.state에 접근이 가능하고 리액트 요소를 반환한다.
//Class
class LifeCycle extends Component {
constructor(props) {
super(props);
}
render
- 컴포넌트를 렌더링할 때 필요한 메서드로 필수 메서드이다.
class LifeCycle extends Component {
render() {
return <h1>렌더링</h1>
}
}
componentDidMount
- 컴포넌트가 DOM에 렌더링 된 후 호출되는 메서드이다. 이 메서드가 호출되는 시점에 우리가 만든 컴포터는가 화면에 나타난 상태다. DOM의 속성을 읽거나 직접 변경하는 작업을 한다.
이 메서드는 컴포넌트를 만들고 첫 렌더링을 마친 후 실행된다.
여기선 주로 DOM을 사용해야하는 외부 라이브러리 연동을 하거나, 해당 컴포넌트에서 필요로하는 데이터를 요청하기 위해 axios, fetch 등을 통하여 ajax 요청을 하거나, DOM의 속성을 읽거나 직접 변경하는 작업을 진행한다.
class LifeCycle extends Component {
componentDidMount() {
...
}
}
componentDidUpdate
- 리렌더링을 완료하고, 화면에 원하는 변화가 반영되고 난 뒤에 호출되는 메서드이다.
컴포넌트가 업데이트 되었을 때, DOM을 조작할 때 활용할 수 있다.
class LifeCycle extends Component {
componentDidUpdate(prevProps, prevState) {
...
}
}
componentWillUnmount
- 이 컴포넌트를 DOM에서 제거할 때 실행된다. 컴포넌트가 화면에서 사라지는 것을 의미하며
이 메서드는 컴포넌트가 화면에서 사라지기 직전에 호출된다.
여기서는 componentDidMount에서 등록한 이벤트를 제거하고, 만약 setTimeout을 사용했다면 clearTimeout을 통하여 제거를 한다.
class LifeCycle extends Component {
coomponentWillUnmount() {
...
}
}
React Hooks
리액트에서 Hook은 함수형 컴포넌트에서 React state와 생명주기 기능을 연동 할 수 있게 해주는 함수다.
Hook은 함수형(functional Component)에서만 사용이 가능 합니다.
규칙
- 최상위에서만 호출 가능! 컴포넌트의 최상위에서만 Hook을 호출 할 수 있다. 반복문, 조건문, 중첩된 함수등에서는 호출이 불가
- React 함수에서만 Hook 호출이 가능하다. 일반적인 JavaScript 함수에서는 호출이 불가하다.
Hook을 사용함으로서 클래스형 컴포넌트보다 쉽고 직관적으로 같은 기능을 만들 수 있다.
useState
- 우리가 프로젝트에서 사용할 데이터의 상태를 관리한다. [state이름,setter이름]=useState()의 형태로 사용된다.
const [state, setState] = useState(initialState);
useEffect
- 기본적으로 React는 위에 class형 컴포넌트 라이프사이클에서 말했듯이 4가지의 변화에 따라 재렌더링이 되는데 useEffect는 처음 렌더링이 되었을 때 한 번만 렌더링 되게 하고 싶을때 사용하는 Hook이다.
- 화면에 렌더링이 완료된 후에 수행되며componentDidMount와 componentDidUpdate, componentWillUnmount가 합쳐진 Hook이다.
- useEffect 안에 return을 사용할 수 있는데 return () => {} 이런식으로 추가해서 쓰면 이 코드는 useEffect가 실행되기 전에 사용되어진다. 그래서 useEffect로 여러번 무언가가 실행되어서 여러개의 무언가가 만들어지게 되면 return () {기존에 있던 무언가를 제거해줘} 하고 짜면 기존의 무언가를 싹 제거한 상태에서 내가 필요한 무언가만 장착할 수 있게된다. 그래서 효율적으로 코드 짜는게 가능해진다.
이 함수를 clean up function이라고 하는데 이 부분이 클래스형 컴포넌트의componentWillUnmount 역할을 한다고 보면 된다.
- 이런 기능을 응용해서 데이터 요청할 때 주로 사용한다.
useEffect(() => {}); // 렌더링 결과가 실제 돔에 반영된 후마다 호출
useEffect(() => {}, []); // 컴포넌트가 처음 나타날때 한 번 호출
useEffect(() => {}, [의존성1, 의존성2, ..]); // 조건부 effect 발생, 의존성 중 하나가 변경된다면 effect는 항상 재생성됩니다.
useRef
- 특정 DOM을 선택할 때 주로 쓰이며 .current 프로퍼티로 전달된 인자로 초기화된 변경 가능한ref 객체를 반환한다. 반환된 객체는 컴포넌트의 전 생애주기를 통해 유지된다.
const refContainer = useRef(null);
useMemo
- useMemo는 메모이제이션 된 값을 반환한다. Component는 state 값이 변경될 때마다 리렌더링이 된다. 값이 변경이 되지 않았는데 값을 재설정 하는 것은 불필요하다.
그렇기 때문에 useMemo는 이미 연산된 값을 리렌더링 시 다시 계산하지 않도록 한다. 오직 의존성이 변경되었을 때에만 메모이제이션된 값만 다시 계산한다. 의존성 배열이 없는 경우 매 렌더링 때마다 새 값을 계산한다.
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
useCallback
- 메모이제이션 된 콜백을 반환합니다. useMemo와 유사하게 이용되며 '함수'에 적용해줍니다.
의존성이 변경되었을때만 변경됩니다. 때문에 특정 함수를 새로 만들지 않고 재사용가능하게 합니다.
*콜백을 반환한다는 것은 콜백 함수를 메모리에 올려놓고, 사용한다는 뜻입니다.
const memoizedCallback = useCallback(
() => {
doSomething(a, b);
},
[a, b],
);