본문 바로가기

[JS] useEffect 용례

[JS] useEffect 용례
*  레퍼런스
-  리액트 공식문서 : useEffect
-  React Hooks에 취한다 - 유튜브

 

미리 알고 있어야 하는 개념

 

useEffect(setup, [dependencies]) 

  • 컴포넌트의 최상위 수준에서 useEffect를 호출하여 Effect를 선언한다.
  • useEffect는 undefined 값을 반환한다.

 

Mount & Unmount

 

useEffect의 setup & cleanup

 

 useEffect가 작동하는 과정은 다음과 같다. (예: 채팅 외부시스템을 가져와서 웹 화면에 구현)

  • 컴포넌트가 마운팅되면, (페이지에 추가) setup 코드가 작동한다. (예: '과일' 주제의 채팅창 열기)
  • 종속성 배열 인자의 값이 변할 때마다 컴포넌트는 리렌더링 된다. (예: 종속성 배열 인자는 채팅창의 주제(과일, 영화....)) 
    • 이때, cleanup 코드가 기존 props와 state로 작동하고,  (예: '과일' 주제의 채팅창 개설)
    • 그 뒤에 setup 코드가 새로운 props와 state로 작동한다.  (예: '영화' 주제의 채팅창 열기)
  • 컴포넌트가 언마운팅될 때, (페이지에서 삭제) cleanup 코드가 마지막으로 작동한다. (예: '영화' 주제의 채팅창 닫기)

 

오른쪽: 위의 [채팅창] 예시 setup & cleanup 코드가 작동하는 모습 (자세한 예시는 아래의 용례 1 내용 참고)

 

Timer 컴포넌트 (외부 시스템)
import React, {useEffect} from 'react';

const Timer = {props) => {
	useEffect( () => {

    const timer = setInterval( () => {
    console.log('타이머 작동 중'); }, 1000);
    
    return () => {
	    clearInterval(timer);
        console.log('타이머 종료'_;
    };

    }, [] );        // 처음 렌더링 될 때만 작동한다.


  return (
  	<div>
    	<span> 타이머를 시작합니다. (콘솔을 보세요!) </span>
    </div>
  );

};

export default Timer;

 

Timer 컴포넌트(외부시스템)을 가져와서 화면에 구현한 App.js
import React, {useState} from 'react';
import Timer from './component/Timer';

function App(){
	const [showTimer, setShowTimer] = useState(false);
    return (
       <div>
        	{showTimer && <Timer />}                       <!-- showTimer가 true일 때만 Timer 컴포넌트가 마운팅된다. -->
            <button onClick={ () => setShowTimer(!showTimer)}> <!-- 버튼을 클릭해주면 showTimer 상태를 변경해준다. -->
            타이머 버튼!                                          <!-- 다시 말해, 버튼을 클릭하면(타이머 컴포넌트가 마운트) -->
            </button>                                          <!-- 다시 또 클릭하면 타이머 컴포넌트가 언마운트 된다. -->
        </div>

    );
}
export default App;

 

useEffect를 써야만 하는 상황

 

useEffect는 컴포넌트를 외부 시스템과 동기적으로 작동할 수 있게 해주는 React Hook이다.

  • useEffect는 비동기적으로 처리된 데이터를 동기적으로 업데이트하고 렌더링할 때 사용되며,
  • 이를 통해 비동기 작업이 완료된 후에 원하는 변수를 업데이트하고 컴포넌트를 렌더링할 수 있다.

 

[React에서 외부시스템의 정의]

일부 컴포넌트는 페이지에 그려지는 동안 네트워크, 일부 브라우저 API 또는 third-party 라이브러리에 연결된 상태를 유지해야 한다. 이러한 시스템들은 React에 의해 제어되지 않으므로 외부라고 한다.

예시)
setInterval()clearInterval()
window.addEventListener()window.removeEventListener()
animation.start() animation.reset().

 

내가 이해한 바에 따라 예를 들면,

 

컴포넌트가 처음으로 마운팅 되고 API(외부 시스템)로 받아온 뉴스 데이터를, 메인 화면에 그려야 하는데 

  • 메인 컴포넌트가 렌더링이 되고나서, 그 뒤에 promise를 통해 뉴스 데이터가 받아와 newsData 등의 변수에 넣어놨다면...?? 
  • 이미 다 렌더링된 상태이기 때문에(데이터가 들어가야할 공간은 비어있음) 화면에 빈 화면이 뜰 것이다.
  • useState를 사용하면 되지 않느냐? --> useState는 비동기적으로 실행된다. (쉽게 얘기하면 내가 원하는 동작보다 한 두 단계 늦다)
  • 따라서 어떤 값이 변경되고 나서 바로 실행되기 위해서(동기적)는 useEffect를 사용해야 한다.

 

이를 해결할 수 있는 방법은

  • (1) 렌더링을 일단 해놓고, 뉴스 데이터를 받아오고 나서 ---> 그 데이터를 다시 만들어진 화면 속에 적용해야 하는 작업이 필요하다.
  • (2) 자연스럽게 하기 위해서는 로딩 화면을 띄워놓고 동시에 뉴스 데이터를 다 받았다면 같이 렌더링하는 방법도 있다.

 

포인트는 이거다.

 

useEffect Hook을 사용하여
컴포넌트의 렌더링 이후에 수행할 작업을 정의할 수 있다.

 

 

 

(용례 1) Connecting to a chat server

  • 이 예에서 ChatRoom구성 요소는 Effect를 사용하여 에 정의된 외부 시스템에 연결된 상태를 유지합니다 chat.js. "채팅 열기"를 눌러 ChatRoom구성 요소를 표시합니다. 이 샌드박스는 개발 모드에서 실행되므로 여기에 설명된 대로 추가 연결 및 연결 해제 주기가 있습니다 . 드롭다운과 입력을 변경 roomId하고 serverUrl사용해 보고 효과가 채팅에 어떻게 다시 연결되는지 확인하십시오. 마지막으로 효과 연결 해제를 보려면 "채팅 닫기"를 누르십시오.
  • 위의 코드에서 ChatRoom 컴포넌트는 외부 시스템 chat.js와 연결을 유지하기 위해 Effect를 쓰고 있다.

 

 

 

포스팅 초반에 [미리 알고 있어야 하는 개념] section에 나왔던 'useEffect의 setup & cleanup' 코드 발췌
  useEffect(() => {
    const connection = createConnection(serverUrl, roomId);  // 외부 시스템
    connection.connect();             // setup 코드
    return () => {                    // cleanup 코드
      connection.disconnect();
    };
  }, [roomId, serverUrl]);

 

(용 2) Listening to a global browser event

  • 외부 시스템의 대표적인 DOM을 react로 제어하기 위해서는 보통 JSX로 이벤트 리스너를 지정하기도 한다.
  • 하지만 위의 방법으로는 전역 window 객체에 연결할 수는 없다.
  • 따라서 아래와 같이 window 객체에 연결하고 이벤트를 수신할 수 있다.

 

 

 

(용 3) Triggering an animation

  • 여기서의 외부 시스템은 animation.js에 있는 animation 라이브러리이다.
  • FadeInAnimationDOM 노드를 인수로 사용하고 노출 start()및 stop()애니메이션을 제어하는 ​​메서드를 호출하는 JavaScript 클래스를 제공한다 .
  • 이 구성 요소는 ref를 사용하여 기본 DOM 노드에 액세스한다.
  • Effect는 참조에서 DOM 노드를 읽고 구성 요소가 나타날 때 해당 노드에 대한 애니메이션을 자동으로 시작한다.

 

 

(용 4) Controlling a modal dialog

  • 이 예에서 외부 시스템은 브라우저 DOM이다.
  • Modal Dialog 컴포넌트는 dialog 엘리먼트를 렌더링한다.
  • Effect를 사용하여 isOpen prop을 showModal()close()메서드 호출과 동기화한다.

 

 

(용 5) Tracking element visibility

  • 이 예에서 외부 시스템은 다시 브라우저 DOM이다.
  • App 컴포넌트는 <LongSection /> 컴포넌트 -> <Box /> 컴포넌트 -> <LongSection /> 컴포넌트 ...를 나열한다.
    • LongSection 컴포넌트는 긴 리스트의 데이터를 렌더링
    • Box 컴포넌트는 파란색 네모 박스 모양의 도형을 렌더링 
  • Box컴포넌트가 뷰포트에 나타나면 배경색이 검은색으로 변경된다.
    • 이를 구현하기 위해 Box 컴포넌트는 Effect를 사용하여 IntersectionObserver API를 사용한다.
    • 이 브라우저 API는 DOM 요소가 뷰포트에 표시될 때 알려준다.

 

 

728x90
⬆︎