이전 포스팅에서 함수 컴포넌트와 useState에 대해 알아보았다.
2022.04.26 - [React] - React - 함수 컴포넌트
이번에 알아볼 것은 React에서 제공해주는 또다른 내장 Hook인 useEffect 이다.
< 목차 >
- Lifecycle (생명주기)
- useEffect
1. Lifecycle (생명주기)
useEffect 함수에 대해 알아보기 위해서는 우선 React에서 얘기하는 Lifecycle에 대해 알고 넘어가야 한다. Lifecycle 혹은 생명주기라고 불리며 component가 랜더되는 시점을 잡아서 이벤트를 걸고 싶을 때 사용하는 개념이다. React에서는 component가 랜더된 시점, component가 리랜더링 된 시점, component가 사라지는 시점들을 잡아서 특정 함수를 실행시킬 수 있는데 이 때 사용되는 것이 바로 생명주기 함수이다.
생명주기 함수에는 componentDidMount( ) , componentDidUpdate( ) , componentWillUnmount( ) 함수가 존재하며 해당 함수들은 클래스 컴포넌트에서만 사용이 가능하다. 각각의 기능은 다음과 같다.
- componentDidMount( ) : 컴포넌트가 랜더 완료되었을 때 최초 1회 실행. ( DOMContentLoaded와 유사 )
- componentDidUpdate( ) : 컴포넌트의 상태가 바뀌었을 때 실행.
- componentWillUnmount( ) : 컴포넌트가 사라질 때 실행.
이러한 생명주기 함수들을 이용하면 component가 생성, 갱신, 삭제되는 각각의 시점을 잡을 수 있고 시점별로 다양한 처리가 가능해진다. 일례로 모든 component가 랜더 완료 된 이후 시점에서 componentDidMount( ) 함수를 이용해 백엔드에 요청을 보낼 수 있고 백엔드에서 알맞은 응답이 왔을 때 this.setState( )를 통해 상태를 변경해 줄 수 있다. 상태가 변경되었기 때문에 component가 리랜더링 되고 이 때 componentDidUpdate( )를 이용하면 상태가 갱신되는 시점에서 원하는 처리를 해줄 수 있다. componentWillUnmount( ) 함수의 경우 component가 사라질 때 실행되는 함수로 보통 socket 종료 시점에서 많이 사용된다.
2. useEffect
useEffect는 함수 컴포넌트에서 사용되는 함수로 React에서 제공해주는 내장 Hook 중의 하나이다. 클래스 컴포넌트의 생명주기 함수와 비슷한 기능을 하는 함수로써 함수 컴포넌트에서는 useEffect 함수를 이용해 componentDidMount( ) , componentDidUpdate( ) , componentWillUnmount( ) 와 비슷한 기능들을 구현할 수 있다. 즉, useEffect Hook은 클래스 컴포넌트의 생명주기 메소드들이 합쳐진 것이라고 생각하면 된다.
useEffect 함수는 다음과 같이 2개의 인자값을 받는데 첫번째 인자값은 콜백함수이고 두번째 인자값은 배열이다.
useEffect(()=>{
// 코드블록
console.log('hello useEffect Hook')
return () => {
console.log('컴포넌트가 삭제된 후 발동')
} // return 값의 기능은 componentWillUnmount()
}, [count])
// 두번째 인자값은 배열
// 배열 안에 상태값이 있으면 componentDidMount() 와 componentDidUpdate()
// 빈 배열이라면 componentDidMount()
첫번째 인자값으로 들어가는 콜백함수는 필수적으로 들어가야하는 값이고 두번째 인자값으로 들어가는 배열은 선택 항목이다. 모든 component가 랜더 완료된 시점에 useEffect 함수의 첫번째 인자값으로 들어간 콜백함수가 최초 1회 실행되며 두번째 인자값인 배열 안에 상태값을 집어넣어 상태가 갱신되었는지 여부를 추적하게끔 할 수 있다. 위와 같이 두번째 인자값인 배열 안에 count 변수가 들어갈 경우 useEffect 함수가 count 변수의 상태를 추적해서 해당 상태값이 변경될 때마다 콜백함수가 실행되게끔 한다. 이는 useEffect 함수가 클래스 컴포넌트의 componentDidUpdate 메소드와 유사하게 동작한다고 볼 수 있다.
또한 첫번째 인자값으로 들어가는 콜백함수 안에서 return값으로 함수를 반환할 수 있는데 위의 코드에서처럼 return값이 존재할 경우 클래스 컴포넌트의 componentWillUnmount 메소드가 실행되는 시점에 return값의 함수가 실행된다. useEffect 함수의 콜백함수 안에서 return을 사용할 때는 return값으로 함수를 넣어야 한다는 점에 유의하자.
만약 두번째 인자값으로 아무런 값이 들어가지 않을 경우 모든 component가 랜더된 이후의 시점에서 최초 1회 콜백함수가 실행된다. 마찬가지로 두번째 인자값이 빈 배열일 경우도 useEffect 함수가 추적하고 있는 상태값이 없으므로 모든 component가 랜더 완료된 시점에 콜백함수가 최초 1회 실행된다. 클래스 컴포넌트의 componentDidMount 메소드처럼 동작한다고 생각하면 된다.
React 공식 문서에서는 useEffect Hook을 이용하면 함수 컴포넌트에서 side effect를 수행할 수 있다고 명시되어 있다. 이전 포스팅에서 만들었던 카운터를 이용해 useEffect 함수가 어떻게 동작하는지 직접 살펴보도록 하자.
// App.js 파일
import Effect from './Components/Effect.jsx'
function App() {
return (
<div className='App'>
<Effect />
</div>
);
}
export default App;
// Effect.jsx 파일
import React, {useState, useEffect} from 'react'
const Effect = () => {
const [count, setCount] = useState(0)
useEffect(()=>{
// 코드블록
console.log('hello effect')
return () => {
console.log('bye effect')
}
},[count])
return(
<div>
<p>You clicked {count} times</p>
<button onClick={ ()=>{ setCount( prev => prev+1) } }>
Click me
</button>
</div>
)
}
export default Effect;
새로고침을 하게 되면 component가 랜더 완료된 시점에서 useEffect 함수의 콜백함수가 실행된다. 그 결과 console.log('hello effect')가 실행되어 콘솔이 찍힌다. 카운터 버튼을 클릭해 count 변수의 상태값을 변경해주면 component가 지워지면서 리랜더링 되어 Effect 함수 전체가 다시 실행된다. 이 때 component가 지워지는 시점에 useEffect 함수의 콜백함수 return값으로 들어간 함수가 실행되면서 console.log('bye effect')가 실행되어 콘솔에 찍힌다. 그리고 리랜더링 되었기 때문에 component가 다시 생성되고 랜더 완료된 시점에 console.log('hello effect')가 실행되어 콘솔에 찍히게 된다.
이처럼 useEffect 함수를 이용하면 클래스 컴포넌트의 생명주기 메소드들이 했던 기능들을 구현할 수 있다. 하지만 useEffect Hook 하나만을 이용해 모든 시점을 정확히 잡아내는 것이 쉬운 일은 아니다. useEffect 함수의 콜백함수가 componentDidMount( )의 시점에서도 실행되고 componentDidUpdate( )의 시점에서도 실행되기 때문이다. 결국 특정 시점을 정확히 잡아내기 위해 콜백함수 안에서 조건문을 사용하게 되고 조건문을 통해 원하는 시점을 잡아내어 작성된 코드들이 실행되게끔 해야한다.
'React' 카테고리의 다른 글
React - useCallback & useMemo (0) | 2022.04.30 |
---|---|
React - useContext & useReducer (1) | 2022.04.29 |
React - 함수 컴포넌트 & useState (2) | 2022.04.26 |
create-react-app 없이 React 구동하기 (0) | 2022.04.21 |
React - css 적용하기 (0) | 2022.04.21 |