useEffect
Side Effect
Rendering in React
- React에서 rendering은 state, props를 기반으로 ui 요소를 그려내는 행위이다.
- Input (state, props)에 따라 다른 UI를 표현하는 함수와도 구조적으로 동일하다.
Side Effect
-
부수효과라고 부른다.
-
함수가 어떤 동작을 할 때 input, output 이외의 다른 값을 조작한다면, 이 함수에는 sideEffect가 있다고 표현한다.
-
대표적으로 Data Fetching, DOM에 직접 접근, 구독(setInterval(), setTimeout())과 같은 행위들이 있다.
-
setInterval(() ⇒ {}, n); // n ms마다 해당 콜백을 실행함
setTimeout(() ⇒ {}, n); // n ms 뒤에 해당 콜백을 실행함
function greetWithSideEffect({ name }) { // Input
// Bad!
document.title = `${name}님 안녕하세요!`; // Side Effect
return <div>{`${name}님 안녕하세요!`}</div>; // Output
}
Side Effect를 함수의 body에서 실행시키면 안된다.
State,props의 변화가 있을 때마다 함수가 실행되는데 매 렌더링 때마다 함수 body에 있는 로직이 실행된다.
렌더링과 무관한 로직이 렌더링 과정에서 실행되기 때문에 렌더링 자체에 영향을 줘 성능 상 악영향을 끼칠 수도 있다.
따라서 이러한 side Effect를 일으키기 적절한 장소로 useEffect hook을 제공한다.
side Effect를 아래 방식처럼 사용해야 한다.
import { useEffect } from 'react';
function greetWithSideEffect({ name }) { // Input
useEffect(() => {
// Good!
document.title = `${name}님 안녕하세요!`; // Side Effect
}, [name]);
return <div>{`${name}님 안녕하세요!`}</div>; // Output
}
useEffect
사용법
import { useEffect } from "react"
// 사용법
useEffect( 실행시킬 동작, [ 타이밍 ] )
document.addEventListener("타이밍", 실행시킬 동작) // 추상화 한 예시
// 매 렌더링마다 Side Effect가 실행되어야 하는 경우
useEffect(() => {
// Side Effect
})
// Side Effect가 첫 번째 렌더링 이후 한번 실행 되고,
// 이후 특정 값의 업데이트를 감지했을 때마다 실행되어야 하는 경우
useEffect(() => {
// Side Effect
}, [value])
// Side Effect가 첫 번째 렌더링 이후 한번 실행 되고,
// 이후 어떤 값의 업데이트도 감지하지 않도록 해야 하는 경우
useEffect(() => {
// Side Effect
}, [])
Clean up Effect
Effect 이후 일어나는 clean up Effect 이다.
전에 일어난 side Effect를 정리할 필요가 있을 때 사용합니다.
만약 우리가 팝업창을 열었을 때 마우스의 x,y 좌표를 계산하여 화면에 출력한다고 하자
그러면 우리가 팝업창을 열었을 때는 side Effect가 발생하지만
팝업창을 닫은 이후에도 side Effect가 발생할 필요가 없기 때문에
Effect를 정리해줘야 한다.
사용법
useEffect(() => {
function handleScroll() {
console.log(window.scrollY)
}
document.addEventListener("scroll", handleScroll)
return () => {
document.removeEventLisnter("scroll", handleScroll)
}
}, [])
주의점은 컴포넌트가 사라지는 시점에 cleanup Effect가 실행되는게 아니고
다음 Effect가 일어나기 전에, cleanup Effect가 실행되는 것입니다.
예시)
const App = () => {
const [count, setCount] = useState(0);
console.log("render", count);
useEffect(() => {
console.log("useEffect Callback", count);
return () => {
console.log("cleanUp", count);
});
}, [count]);
return <div onClick={() => setCount(count + 1)}>Hello</div>;
};
render, 0 useEffect Callback, 0
// 클릭
render, 1
cleanUp, 0
useEffect Callback, 1
// 클릭
render, 2
cleanup, 1
useEffect Callback, 2
댓글남기기