* 레퍼런스
- 리액트 공식문서 : useEffect
- React Hooks에 취한다 - 유튜브
미리 알고 있어야 하는 개념
useEffect(setup, [dependencies])
- 컴포넌트의 최상위 수준에서 useEffect를 호출하여 Effect를 선언한다.
- useEffect는 undefined 값을 반환한다.
Mount & Unmount
useEffect의 setup & cleanup
useEffect가 작동하는 과정은 다음과 같다. (예: 채팅 외부시스템을 가져와서 웹 화면에 구현)
- 컴포넌트가 마운팅되면, (페이지에 추가) setup 코드가 작동한다. (예: '과일' 주제의 채팅창 열기)
- 종속성 배열 인자의 값이 변할 때마다 컴포넌트는 리렌더링 된다. (예: 종속성 배열 인자는 채팅창의 주제(과일, 영화....))
- 이때, cleanup 코드가 기존 props와 state로 작동하고, (예: '과일' 주제의 채팅창 개설)
- 그 뒤에 setup 코드가 새로운 props와 state로 작동한다. (예: '영화' 주제의 채팅창 열기)
- 컴포넌트가 언마운팅될 때, (페이지에서 삭제) cleanup 코드가 마지막으로 작동한다. (예: '영화' 주제의 채팅창 닫기)
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
'FE > React' 카테고리의 다른 글
React Diffing Algorithm - 상태변화를 감지할 수 있도록 하는 React의 비교 알고리즘 (0) | 2023.05.19 |
---|---|
[React] Virtual DOM (0) | 2023.05.19 |
쇼핑몰 앱에서 Redux를 이용한 상태 관리 (2) (0) | 2023.04.26 |
쇼핑몰 앱에서 Redux를 이용한 상태 관리 (1) (0) | 2023.04.26 |
Redux로 간단한 Count 기능 구현하기 (0) | 2023.04.24 |