React useEffect 사용하기
📝 개요
- 웹 사이트를 만들다 보면 화면에 보일 수 있는 데이터를 서버에서 받아오기도 해야 하고,
state
가 바뀔 때마다 함수를 실행 시키거나, 이벤트 리스너를 달았다가 해제하는 등의 동작이 필요할 수 있다. 이 때useEffect
훅이 필요하며, 빈번히 사용되는 중요한 개념이므로useEffect
에 대해서 정리하는 시간을 갖는다.
React에서 함수 컴포넌트의 rendering이란 state
, props
기반으로 UI요소를 그려내는 행위이다. (state, props) => UI
와 같이 표현이 가능하다. 즉, rendering 결과물은 UI요소로 JSX 문법으로 무엇이 나타날지 적어둔 component이다.
Side Effect
컴퓨터 과학에서 함수가 결과값 이외에 다른 상태를 변경시킬 때 '부작용'이 있다고 말한다. 함수가 동작할 때 input
, output
이외의 다른 값을 조작한다면, 이 함수에는 side effect(부수효과)가 있다고 표현한다. 함수 컴포넌트에서의 side effect는 렌더링이 아닌 외부 세계에 영향을 주는 어떠한 행위이다.
대표적으로 Data Fetching, DOM에 접근(ex. EventListener
등록), 구독(ex. setInterval
)등이 있다. 이들은 컴포넌트에서 꼭 필요한 대표적인 side effect에 해당한다.
// input을 받아 output을 내는 본질적인 함수로 side effect가 없는 순수함수
const sumOne = (num) => {
return num+1;
}
// console창은 외부의 값이다. 외부 요소에 접근, 읽기, 수정은 모두 side effect에 해당
const sumOne = (num) => {
console.log("num = ", num);
return num+1;
}
// 당연히 함수 내에 외부의 값 plusNum을 읽었으니 side effect에 해당
const plusNum = 30;
const sumNum = (num) => {
num + plusNum;
}
useEffect
side effect들을 함수의 body(render)
에서 실행시키면 안된다. 함수 컴포넌트의 리턴 값은 UI 요소이며, state
, props
변화가 있을 때마다 함수가 실행된다. 즉, 매 렌더링마다 함수 body
에 있는 로직이 실행된다는 의미이다. 렌더링과 무관한 로직이 렌더링 과정에서 실행되면 렌더링 자체에 영향을 주기 때문에 성능에 악영향을 끼친다.
side effect를 일으키기 적당한 장소로 useEffect
hook을 제공한다. useEffect
는 side effect를 렌더링한 이후에 동작한다. 어려운 연산이나 서버에서 데이터 가져오는 작업 등을 useEffect
에 작성하면 효율적으로 웹 페이지를 보여줄 수 있다.
Rendering Cycle with useLayoutEffect
useEffect
hook이 등장하기 이전에는 클래스함수로 기존 컴포넌트 Lifecycle에 간섭하려면 아래와 같은 코드를 사용했다.
class lifecycle extends React.Component {
componentDidMount() {
// 컴포넌트 페이지 장착시
}
componentDidUpdate() {
// 컴포넌트 업데이트시
}
componentWillUnmount() {
// 컴포넌트가 필요 없을시
}
}
다음으로 useEffect
hook 사용 방법에 대해서 알아보자.
// useEffect(실행시킬 동작, [타이밍])
// 1. 매 Rendering 마다 Side Effect가 실행되어야 하는 경우
useEffect(() => {
// SIDE EFFECT
})
// Side Effect가 첫 Rendering 이후 한 번 실행되고, 이후 특정 값(value)의 업데이트(state 변경) 감지했을 때 실행되어야 하는 경우
useEffect(() => {
// SIDE Effect
}, [value])
// Side Effect가 첫 Rendering 이후 한 번 실행되고, 이후 어떤 값의 업데이트도 감지하지 않도록 해야 하는 경우
useEffect(() => {
// SIDE EFFECT
}, [])
// 추가
useEffect(() => {
return() => {
// useEffect 동작 이전에 실행되는 부분 작성
}
})
- 컴포넌트가 렌더링 된다. 최초로 진행되는 렌더링은 브라우저에 처음으로 이 컴포넌트가 보여졌다는 의미로
mount
라고 표현한다. useEffect
첫 번째 인자로 넘겨준 함수 callback함수가 실행된다 => side effectstate
나props
가 변경된 경우, re-render된다.useEffect
는 두 번째 인자에 들어 있는 의존성 배열을 체크한다. 만약 두 번째 인자에 아무 값도 넘기지 않거나, 배열에 들어있는 값 중 하나라도 업데이트 됐다면 첫 번째 인자로 넘긴 callback이 실행된다. 반대로 빈 배열이라면 아무런 동작을 하지 않는다.- 만약 앞서 일으킨 effect에서
state
나props
를 변경시켰다면 re-render을 반복한다. - 컴포넌트가 필요 없어지면 화면에서 사라진다. 컴포넌트가 브라우저 화면에서 사라졌다는 의미로
unmount
라고 표현한다.
Cleanup Effect
useEffect(() => {
function handleScroll() {
console.log(window.scrollY)
}
document.addEventListener("scroll", handleScroll)
return () => {
document.removeEventListener("scroll", handleScroll)
}
}, [])
앞서 발생한 side effect를 정리할 필요가 있을 때 사용한다. 해당 이벤트를 구현하는 페이지를 벗어나면 이벤트는 더 이상 필요 없으며, 이 경우 발생시킨 effect를 정리해야 하는데 이 때마다 cleanup effect를 일으킬 수 있도록 useEffect
내에 해당 로직을 정리하는 동작을 정의하면 된다.
순서 이해하기
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)}>CLICK</div>;
};
export default Foo;
/*
render, 0
useEffect Callback, 0
<클릭 후>
render, 1
cleanUp, 0
useEffect Callback, 1
*/
'⭐️ Library & Framework > ReactJS' 카테고리의 다른 글
[React] 카카오 소셜 로그인 구현하기 (0) | 2022.06.11 |
---|---|
React Mockdata (0) | 2022.05.19 |
React Router 사용하기 (0) | 2022.05.12 |
React 공식문서 주요개념 읽기 - 2 (0) | 2022.05.10 |
React에 Font Awesome 적용하기 (0) | 2022.05.09 |
댓글
이 글 공유하기
다른 글
-
[React] 카카오 소셜 로그인 구현하기
[React] 카카오 소셜 로그인 구현하기
2022.06.11 -
React Mockdata
React Mockdata
2022.05.19 -
React Router 사용하기
React Router 사용하기
2022.05.12 -
React 공식문서 주요개념 읽기 - 2
React 공식문서 주요개념 읽기 - 2
2022.05.10