userEffect()는 어떠한 컴포넌트가 Mount(화면에 첫 렌더링), Update(다시 렌더링), Unmount(화면에서 사라질 때) 되었을 때 특정 작업을 처리할 코드를 실행시키고 싶을 때 사용한다.
useEffect에는 두 가지 형태가 있다.
첫 번째는 인자로 콜백함수 하나만 받는 경우이다.
useEffect( () => {
//실행할 작업
})
두번째로는 아래와 같이 두번째 인자로 배열을 받는다.
useEffect( () => {
//실행할 작업
}, [value])
dpendency array
라고도 한다.만약 useEffect()에서 어떤 서비스에 구독하는 코드를 넣었다면 이후에 구독을 해제해주는 clean up, 정리 작업을 처리해야한다.
이럴 때 useEffect()의 콜백함수안에 리턴 값으로 함수를 넣어주면 된다.
useEffect( () => {
// 구독
return () => {
// 구독 해지
}
}, [])
이렇게 함수를 return 해주면 해당 컴포넌트가 unmount될 때 혹은 다음 렌더링시 불릴 useEffect()가 실행되기 이전에 그 함수가 실행된다.
import React, {useState, useEffect} from 'react';
function App() {
const [count, setCount] = useState(1);
const [name, setName] = useState("");
const handleCountUpdate = () => {
setCount(count + 1)
}
const handleNameUpdate = (e) => {
setName(e.target.value)
}
useEffect(()=>{
console.log("무거운 작업...");
})
return (
<div>
<button onClick={handleCountUpdate}>Update</button>
<div>count : {count}</div>
<input onChange={handleNameUpdate}></input>
<span>name : {name}</span>
</div>
);
}
export default App;
다음과 같은 코드는 컴포넌트가 렌더링 될 때마다 useEffect()가 잘 작동하는 것을 볼 수 있다.
하지만 name에서 입력할 때마다 무거운 작업을 계속해서 하게 되어 비효율적이라는 것을 알 수 있다.
매번 렌더링 될 때마다 useEffect()를 실행시키는게 아니라 name이 바뀌었을 때는 무시하고 count가 변경되었을 때만 useEffet()를 실행시키려면 어떻게 해야할까?
useEffect( () => {
console.log("무거운 작업..")
}, [count])
다음과 같이 배열의 값으로 state의 값을 주면 해당 state에만 적용이 된다.
즉, Mount가 될 때와 [] 안의 값이 변경될 때에만 실행된다.
import React, {useState, useEffect} from 'react';
import Timer from './component/Timer'
function App() {
const [showTimer, setShowTimer] = useState(false);
return (
<div>
{/* showTimer가 true일때만 보여주기 */}
{ showTimer && <Timer />}
<button onClick={()=> setShowTimer(!showTimer)}>Toggle Timer</button>
</div>
);
}
export default App;
import React, {useEffect} from 'react';
function Timer(props) {
useEffect(()=>{
const timer = setInterval(()=>{
console.log('타이머 돌아가는 중..');
}, 1000);
}, []);
return (
<div>
<span>타이머를 시작합니다. 콘솔을 보세요!</span>
</div>
);
}
export default Timer;
해당 코드는 toggle 버튼이 false여도 타이머는 계속해서 돌아간다.
하지만 false일 때 작업을 하지 않으려면 어떻게 해야할까?
import React, {useEffect} from 'react';
function Timer(props) {
useEffect(()=>{
const timer = setInterval(()=>{
console.log('타이머 돌아가는 중..');
}, 1000);
return () => {
clearInterval(timer);
}
}, []);
return (
<div>
<span>타이머를 시작합니다. 콘솔을 보세요!</span>
</div>
);
}
export default Timer;
이와 같이
return () => {
clearInterval(timer);
}
return에 컴포넌트가 unmount 될 때 실행할 코드를 작성해주면 된다.
쉽게 말하면 Timer 컴포넌트가 unmount될 때 즉, 화면에서 사라질 때 실행된다.