useEffect()는 두 개의 파라미터를 가질 수 있다고 했다.
useEffect(function, deps)
- function은 실행하고자 하는 함수이고, 의존값인 deps는 function을 실행시킬 조건으로 배열 형태를 띈다.
📌 deps를 생략하면 해당 컴포넌트가 랜더링될 때마다 useEffect()를 실행한다.
useEffect(()=> {
console.log("랜더링될 때마다 실행된다.");
});
📌 맨 처음 랜더링될 때 1번만 useEffect()를 실행하고 싶다면 deps에 빈 배열 ([])을 넣으면 된다.
useEffect(()=>{
console.log("맨 처음 랜더링될 때만 실행된다.");
}, []);
📌 특정값이 업데이트될 때만 useEffect()를 실행하고 싶을 때는 deps 안에 실행 조건을 넣는다.
useEffect(()=>{
console.log('number changed: ', number);
console.log("number 값이 업데이트될 때만 실행된다.");
}, [number]);
📌 useEffect()가 동작하기 전에 특정 코드를 실행하고 싶다면 return문을 이용하면 된다.
useEffect(()=>{
/* 그 다음 여기 코드 실행 */
return ()=>{
/* 여기에 있는 코드 먼저 실행 */
}
}, [count])
📌 useEffect()가 반환할 수 있는 함수인 clean up function을 이용한다. unmount될 때만 clean up 함수를 실행시키고 싶다면 deps에 빈 배열을 넣는다.
useEffect(()=>{
console.log(number);
return ()=>{
console.log(cleanUp 함수 실행된다.);
};
}, []);
📌 만약 특정 값이 업데이트되기 직전에 cleanup 함수를 실행하고 싶으면 deps에 해당 값을 넣으면 된다.
지난 시간에 배운 내용을 바탕으로 상세 페이지에 방문하고 나서 2초 뒤에 박스가 사라지는 기능을 구현해보자.
자바스크립트로 n초 후에 코드를 실행하고 싶을 때 사용하는 setTimeout 함수 사용법은 다음과 같다.
setTimeout ( ()=> { n초 후 실행할 코드 }, n*1000 );
리액트에서는 useEffect 안에 js 코드와 html 태그를 그대로 넣어서 보였다 안 보였다 바꿀 수 없으므로 이 동작을 해주는 일종의 스위치를 생성해주어야 한다. 먼저 메인 컴포넌트에서 useState를 이용해 이 기능을 구현해보자.
function DetailPage() {
let [alert, setAlert] = useState(true);
return (
{
// 삼항연산자
alert == true
? <div className='alert alert-warning'>
2초 이내 구매시 할인
</div>
: null
}
)
}
위 코드는 alert라는 state를 true로 바꾸면 '2초 이내 구매시 할인'이 보이고, alert를 false로 바꾸면 보이지 않게 하는 코드이다.
이 코드에 DetailPage에 접속하고 2초 뒤 보이지 않게 하는 기능을 추가해보자. setTimeout 함수와 useEffect()를 사용하자.
function DetailPage() {
let [alert, setAlert] = useState(true);
useEffect(()=>{
setTimeout(()=>{setAlert(false)}, 2000);
}, []) // 맨 처음 mount될 때만 실행
return (
{
// 삼항연산자
alert == true
? <div className='alert alert-warning'>
2초 이내 구매시 할인
</div>
: null
}
)
}
여기서 코드를 더 발전시키려면 clean up function을 사용하면 된다. 현재 이 코드는 setTimeout()을 사용할 때마다 타이머가 하나씩 생성된다. 이를 useEffect() 안에서 만들었으니 컴포넌트가 마운트될 때마다 실행되는데, 만약 코드를 잘못 짜면 타이머가 엄청 많이 생성되는 상황이 발생할 수도 있다.
이러한 버그를 예방하기 위해서 기존의 타이머를 싹 정리해주는 코드가 필요하다. 이럴 때 return()=>{}을 이용하면 된다!
useEffect(()=>{
let a = setTimeout(()=>{ setAlert(false) }, 2000)
return ()=>{
clearTimeout(a)
}
}, [])
useEffect(()=>{실행할 코드})
useEffect(()=>{실행할 코드}, [])
useEffect(()=>{
return ()=>{
먼저 실행할 코드
}
})
useEffect(()=>{
return ()=> {
실행할 코드
}
}, [])
useEffect(()=>{
실행할 코드
}, [state])