Front-end/React

[React] React Hooks - useEffect, useLayoutEffect

Bay Im 2024. 2. 23. 09:40

React Hooks - useEffect

  • useEffect란
    • 컴포넌트가 랜더링 될 때 특정 작업(side effect)을 실행할 수 있도록 하는 것
      • side effect란 컴포넌트가 랜더링 된 이후에 비동기로 처리되어야 하는 부수적인 효과
    • componentDidMount 시점에 비동기로 실행 (alert, focus, sound 등 After DOM 처리)
    • 함수형 컴포넌트에서 return JSX(render) 다음에 실행
    • 정리(clean-up) 코드는 componentWillUnMount 시점에 실행되고, 의존 관계 배열(Dependency Array)가 비워져 있다면 1회만 실행 된다.
  • 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);
        }, []);
        …
  • 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