React 05. useEffect

윤태현·2023년 6월 28일
0

REACT

목록 보기
5/19
post-thumbnail

📑 useEffect

useEffect란?

  • React의 내장 Hook 중 하나로, 컴포넌트가 렌더링된 이후에 비동기 작업을 수행하기 위해 사용

  • 데이터 fetching, subscription, 또는 수동으로 React 컴포넌트의 DOM을 변경해야 하는 경우에 쓰임

  • 데이터를 가져오거나, 이벤트 리스너를 설정, 타이머 설정 등의 side effect를 처리

  • side effect를 그룹화하여 코드를 분리하고 관리할 수 있음, 코드의 가독성을 높이고 각 side effect의 독립성을 유지할 수 있음.

function ExampleComponent() {
  
  	// API 호출 useEffect
  	useEffect(() => {
    	fetchData();
  	}, []);

  	// 이벤트 리스너 설정 useEffect
  	useEffect(() => {
    	window.addEventListener('resize', handleResize);

    	// 컴포넌트 언마운트 또는 재실행 전에 이벤트 리스너 제거
    	return () => window.removeEventListener('resize', handleResize);
  	}, []);

  	// ...
}

📑 useEffect 사용법

1. useEffect import

import React, { useEffect } from 'react';

2. useEffect 사용

useEffect(() => {
  	// 컴포넌트가 렌더링된 후에 실행될 코드를 여기에 작성합니다.
}, [/* 의존성 배열 */]);
  • 첫 번째 인자 : 렌더링 이후에 실행되는 함수
  • 두 번째 인자 : 의존성 배열 (선택적으로 사용)

3. useEffect 의존성 배열

3-1. 의존성 배열이 없는 경우

  • useEffect 안의 함수는 컴포넌트가 렌더링 될 때마다 렌더링 이후에 실행
useEffect(() => {
  	console.log('렌더링 시 출력');
});

3-2. 의존성 배열이 빈 배열인 경우

  • useEffect 안의 함수는 컴포넌트가 처음 마운트(DOM 객체가 생성되고 브라우저에 나타나는 것) 될 때만 실행
useEffect(() => {
  	console.log('처음 렌더링 시에만 출력');
}, []);

3-3. 의존성 배열이 값들을 포함하는 경우

  • useEffect 안의 함수는 컴포넌트가 처음 마운트 될 때, 그리고 배열에 명시된 값들이 변경될 때마다 실행
const [count, setCount] = useState(0);

useEffect(() => {
  	console.log('count의 값이 변할 때마다 출력');
}, [count]);

return (
	<>
    	<h1>{count}</h1>
    	<button onClick={() => setCount(count+1)}>클릭</button>
    </>
)

📑 useEffect 주의할 점

1. 의존성 배열

  • 배열에 포함된 변수들의 값이 변할 때마다 useEffect가 다시 실행 되기 때문에, 의존성 배열을 빼놓거나 잘못 관리하면 예상치 못한 버그를 유발할 수 있음.

잘못된 예시

  • 의존성 배열을 누락하는 경우
const [count, setCount] = useState(0);

useEffect(() => {
  	document.title = `You clicked ${count} times`;
  	// 의존성 배열에서 'count'를 빠뜨림
}, []);

올바른 예시1

  • 의존성 배열을 올바르게 사용하는 경우
const [count, setCount] = useState(0);

useEffect(() => {
  	document.title = `You clicked ${count} times`;
  	// 'count'를 의존성 배열에 포함
}, [count]);

올바른 예시2

  • 여러 상태를 의존성 배열에 포함하는 경우
const [count, setCount] = useState(0);
const [name, setName] = useState('John');

useEffect(() => {
  	document.title = `${name} clicked ${count} times`;
  	// 'count'와 'name' 모두 의존성 배열에 포함
}, [count, name]);

2. 정리 함수

  • useEffect 내부에서 반환하는 함수

  • 컴포넌트가 언마운트 (DOM에서 제거되는 과정)되거나, useEffect가 재실행되기 전에 호출

  • 이 함수를 사용해 이벤트 리스너를 제거하거나, 타이머를 정리하는 등의 작업을 수행해야 함

  • 정리 함수를 빼놓으면 메모리 누수 등의 문제를 유발할 수 있음

// App.js
function App() {
  const [show, setShow] = useState(true);

  return (
    	<div>
      		{show && <Timer />}
      		<button onClick={() => setShow(!show)}>Toggle Timer</button>
    	</div>
  );
}

// Timer.js
const Timer = () => {
	useEffect(() => {
      	// 컴포넌트가 마운트 되었을 때 실행
    	const timer = setInterval(() => {
        	console.log('타이머 시작');
        }, 1000);
      
        return () => {
            // 컴포넌트가 언마운트될 때 실행
        	clearInterval(timer);
            console.log('타이머 종료');
        }
    }, []);
  
    return (
    	<div>
        	<span>타이머를 시작합니다.</span>
        </div>
    )
}

3. 비동기 작업

  • useEffect 내에서 비동기 함수를 직접 호출하면 경고가 발생

  • useEffect 내부에서 새로운 함수를 선언하고 그 함수 안에서 비동기 작업을 수행해야 함

  • useEffect 는 정리 함수를 반환해야 하는데, 비동기 함수는 항상 Promise를 반환하기 때문에 React는 useEffect 함수에서 Promise를 반환하게 하지 않도록 경고를 띄움

잘못된 예시

  • 내부에서 직접 비동기 함수를 호출
  • useEffect가 비동기 함수로 선언되었기 때문에, Promise를 반환하게 되는데 React는 허용하지 않아서 오류 발생
useEffect(async () => {
  	const response = await fetch('https://api.example.com/data');
  	const data = await response.json();
  	console.log(data);
}, []); // 의존성 배열

올바른 예시1

  • useEffect 내부에서 별도의 함수를 선언하여 비동기 작업 수행
  • useEffect 내부에 별도의 비동기 함수를 선언하고 호출
  • useEffect는 정상적으로 undefined를 반환하고, 별도의 함수에서 비동기 작업을 수행
useEffect(() => {
  	async function fetchData() {
    	const response = await fetch('https://api.example.com/data');
    	const data = await response.json();
    	console.log(data);
  	}

  	fetchData();
}, []); // 의존성 배열

올바른 예시2

  • 비동기 작업의 결과를 상태에 저장
  • API로부터 데이터를 가져와서 화면에 표시해야 하는 경우에 자주 사용
const [data, setData] = useState(null);

useEffect(() => {
  	async function fetchData() {
    	const response = await fetch('https://api.example.com/data');
    	const data = await response.json();
    	setData(data);
  	}

  	fetchData();
}, []); // 의존성 배열

0개의 댓글