useEffect란?
어떤 컴포넌트가 Mount 되었을 때, Update 될 때, UnMount 되었을 때 특정작업을 처리할 코드를 실행시킬 때 사용한다.
React 컴포넌트의 Lifecycle
Mount (화면에 나타나는 것) -> Update (업데이트, 리렌더) -> UnMount (화면에서 사라지는 것)
React Component Lifecycle Methods
출처 : https://projects.wojtekmaj.pl/react-lifecycle-methods-diagram/
React는 기본적으로 Lifecycle마다 실행할 수 있는 Method를 가지고 있다.
하지만 이 Method들은 Class형 컴포넌트에서 만 사용할 수 있다.
함수형 컴포넌트에서는 사용할 방법이 없을까?
바로 React Hooks를 통해서 사용할 수 있다.
클래스형 컴포넌트만 가지고 있는 기능을 함수형 컴포넌트에서 Hooking 하여 사용하는 것을 React Hooks라고 한다.
React Hooks를 사용하면 함수형 컴포넌트에서도 useState, useEffect, useRef 등을 사용할 수 있게 도와준다.
그렇다면 왜 Class형 컴포넌트를 사용하지 않고 React Hooks를 사용하면서 까지 함수형 컴포넌트를 사용할까?
Class형 컴포넌트를 작성할 때 함수형 컴포넌트를 작성할 때 보다 코드가 길어지고 복잡하고 중복 코드를 많이 사용해야 하므로 Class형보다는 함수형 컴포넌트를 사용한다.
useEffect 사용방법
기본 형태
useEffect(()=>{작업})
useEffect훅은 인자로 콜백 함수를 받는다.
간단하게 콜백 함수는 다른 함수의 인자로 전달된 함수를 의미한다.
1. 인자로 하나의 콜백 함수만 받는 형태
useEffect(()=>{작업})
컴포넌트가 Mount 될 때 & 컴포넌트가 Update 될 때마다 콜백 함수를 수행한다.
import { useState, useEffect } from "react";
function App() {
const [count, setCount] = useState(0);
const [text, setText] = useState('')
useEffect(()=>{
console.log('Update')
})
return (
<div>
<span>누른 횟수 : {count}번</span>
<br />
<button onClick={()=>setCount(count+1)}>count</button>
<br/>
<br/>
<span>입력 : {text}</span>
<br/>
<input value={text} onChange={(e)=>setText(e.target.value)}/>
</div>
);
}
export default App;
결과
처음 React를 시작할 때 Mount 되면서 콜백 함수가 1번 수행되었다.
count를 5번 누르니까 5번 상태 변화가 발생하여 콜백 함수가 5번 수행되었다.
input에 값을 입력을 할 때마다 상태 변화가 발생을 하여 콜백 함수가 14번 수행되었다.
즉, 컴포넌트가 처음 Mount 될 때와 컴포넌트가 Update 될 때마다 useEffect안에 있는 콜백 함수가 계속 수행된다는 것을 알 수 있다.
2. 첫 번째 인자는 콜백함수 두 번째 인자는 배열(dependency array)을 받는 형태
useEffect(()=>{작업},[value]);
컴포넌트가 Update 될 때마다 실행되는 것이 아닌 컴포넌트가 Mount 될 때 & 배열 안에 들어있는 요소의 값이 바뀔 때만 콜백 함수가 수행된다.
import { useState, useEffect } from "react";
function App() {
const [count, setCount] = useState(0);
const [text, setText] = useState('')
useEffect(()=>{
console.log(`count is update : ${count}`)
},[count])
return (
<div>
<span>누른 횟수 : {count}번</span>
<br />
<button onClick={()=>setCount(count+1)}>count</button>
<br/>
<br/>
<span>입력 : {text}</span>
<br/>
<input value={text} onChange={(e)=>setText(e.target.value)}/>
</div>
);
}
export default App;
결과
dependency array에 count를 넣어서 useEffect의 콜백 함수는 Mount 되었을 때 & count가 변화될 때만 수행된다.
3. 두 번째 인자에 빈 배열(dependency array)을 받는 형태
useEffect(()=>{작업},[]);
만약 빈 배열을 전달해 주면 Mount 될 때 만 콜백 함수가 수행된다.
import { useState, useEffect } from "react";
function App() {
const [count, setCount] = useState(0);
const [text, setText] = useState('')
useEffect(()=>{
console.log('Mount')
},[])
return (
<div>
<span>누른 횟수 : {count}번</span>
<br />
<button onClick={()=>setCount(count+1)}>count</button>
<br/>
<br/>
<span>입력 : {text}</span>
<br/>
<input value={text} onChange={(e)=>setText(e.target.value)}/>
</div>
);
}
export default App;
결과
빈 배열을 전달해 주어서 처음 Mount 될 때 만 콜백 함수가 수행된다.
4. return이 들어간 형태 (Clean Up)
useEffect(()=>{
// 구독
return()=>{
// 구독 해제
}
},[])
useEffect에 이벤트 리스너를 등록했다면 등록한 리스너를 제거해 주는 정리작업을 해야 한다.
정리작업을 처리하려면 useEffect의 return값으로 함수를 넣어 주면 된다.
함수를 리턴하면 해당 컴포넌트가 Unmount 될 때 함수가 실행된다.
import { useState, useEffect } from "react";
const UnmoutTest = () => {
useEffect(()=>{
console.log("Mount")
console.log("구독중")
return ()=>{
console.log("UnMount")
console.log("구독해제")
}
},[])
return <div>Unmout Test Component</div>
}
function App() {
const [visible, setVisible] = useState(false);
const toggle = () => setVisible(!visible)
return (
<div>
<button onClick={toggle}>구독/구독해제</button>
{visible && <UnmoutTest/>}
</div>
);
}
export default App;
결과
버튼을 처음에 누르면 visible이 true가 되면서 UnmoutTest 컴포넌트가 반환되어서 화면에 렌더링이 된다.
그리고 UnmoutTest 컴포넌트가 Mount 되어서 console 창에 Mount와 구독 중을 띄운다.
다시 버튼을 누르게 되면 visible이 false가 되면서 UnmoutTest 컴포넌트가 렌더링이 안된다.
그러면 UnmoutTest 컴포넌트가 UnMount 되어서 console 창에 unMount와 구독해제를 띄운다.