React Hooks - useEffect
- useEffect란
- 컴포넌트가 랜더링 될 때 특정 작업(side effect)을 실행할 수 있도록 하는 것
- side effect란 컴포넌트가 랜더링 된 이후에 비동기로 처리되어야 하는 부수적인 효과
- componentDidMount 시점에 비동기로 실행 (alert, focus, sound 등 After DOM 처리)
- 함수형 컴포넌트에서 return JSX(render) 다음에 실행
- 정리(clean-up) 코드는 componentWillUnMount 시점에 실행되고, 의존 관계 배열(Dependency Array)가 비워져 있다면 1회만 실행 된다.
- 컴포넌트가 랜더링 될 때 특정 작업(side effect)을 실행할 수 있도록 하는 것
- import
- import { useEffect } from ‘react’;
- 사용
- 기본 형태
-
// 기본 useEffect(() => { ... // 수행할 내용들 }); // 비어있는 의존관계 배열 추가 useEffect(() => { ... // 수행할 내용들 }, []); // 의존관계 배열 값 추가 let something = 1; useEffect(() => { ... // 수행할 내용 }, [something]); // clean up 함수 useEffect(() => { ... // 수행할 내용 return () => { ... // cleanup } });
-
- cleanup 함수
- useEffect( () ⇒ { 수행코드; return () ⇒ 정리코드; }, [의존관계배열: setState의 observer에 등록]);
- useEffect(function, deps)
- function: 수행하고자 하는 작업
- deps: 검사하고자 하는 특정 값 배열이나 빈 배열
- 예시 1
- Login component에 로그인하라는 alert 띄우기
const Login = () => { … useEffect(() => { alert('로그인해주세요!'); return () => { // 정리(cleanup) 함수 alert('로그인 되셨어요'); }; }, []); }
- 기본 형태
- useEffect call twice
- 개발환경 + Strict Mode에서 의존 관계 배열이 비워져있을 때 2회 호출 (Mount - UnMount - Mount)
- Mount는 컴포넌트가 최초로 나타낼 때, UnMount는 사라질 때
- rendering은 컴포넌트가 Mount 된 후 컴포넌트가 호출 될 때
- cleanup 해주고 2회 호출되어도 안전한 코딩을 해야함 (ex. timer, eventListener, data, add, remove)
- 예시
-
const [goodSec, setGoodSec] = useState(0); useEffect(() => { const intl = setInterval(() => { setGoodSec((pre) => pre + 1); }, 1000); return () => clearInterval(intl); }, []); …
-
- 개발환경 + Strict Mode에서 의존 관계 배열이 비워져있을 때 2회 호출 (Mount - UnMount - Mount)
- useEffect with Promise
- Promise는 실행될 때 callback 함수를 background로 제어를 넘긴다.
- re-render 등으로 UnMount시 Promise는 background에 존재하므로 cleanup 되지 않는다.
- cleanup 코드에서 Promise를 중지(abort)해줘야 2번 render되지 않는다.
- controller = new AbortContoller();
- const { signal } = controller;
- fetch(url, { signal });
- useRef with useEffect
- componentDidMount 되기 전에 DOM 참조 안된다.
- <element ref={xRef} />: 여기서 element가 Mount되기 전에는 xRef는 undefined | null
- 자식의 DOM을 useRef로 참조 시 forwardRef + useEffect 필수
- 예시
- Login.userIdRef input에 focus 주기
const Login = () => { … useEffect(() => { console.log('Login, please!'); userIdRef.current?.focus(); return () => { console.log('로그인 되셨어요'); }; }, []); // 단 1번의 효과 }
- 컴포넌트 외부에서 DOM을 올바르게 참조하기
// My.tsx {session.loginUser ? <Profile ref={logoutBtnRef} /> : <Login />} // Profile.tsx const Profile = forwardRef((props, ref) => { … <button ref={ref}>Logout</button> Profile.displayName = 'Profile';
React Hooks - useLayoutEffect
- useLayoutEffect란
- layou(render-tree) 직후 mount(painting) 전 동기적으로 실행 (DOM을 화면에 그리기 직전에 호출)
- rendering → useLayoutEffect → [painting & display 동시(비동기) useEffect(didMount)]
- DOM의 좌표와 크기 등은 모두 결정된 후 화면에 그리기 전에 완료해야 하므로 동기(sync, block)로 실행
- useEffect와 같이 claenup 및 의존 관계 배열 사용은 동일
- 사용
- 예시
useLayoutEffect(() => { // ← 만약 useEffect로 하면 거의(컴퓨터가 빠르면 찰나의 차이) 동일 window.addEventListener('mousemove', catchMousePosition); return () => window.removeEventListener('mousemove', catchMousePosition); })
React Hooks - useEffect와 useLayoutEffect의 차이
- useEffect
- mount 직후 (painting과 비동기로 실행)
- useLayoutEffect
- rendering 직후 mount(painting) 전 실행
'Front-end > React' 카테고리의 다른 글
[React] React Hooks - useReducer (0) | 2024.02.29 |
---|---|
[React] React Hooks - useCallback, useMemo, memo, useId (0) | 2024.02.29 |
[React] React Hooks - useContext (0) | 2024.02.23 |
[React] React Hooks - forwardRef (0) | 2024.02.21 |
[React] React Hooks - useRef (0) | 2024.02.20 |