React

useEffect 와 useEffect 를 사용해 서버에 데이터 가져오기 요청하기

히새 2023. 8. 18. 00:13
function 히새() {


   function 안녕() {
    
   }


}

히새()

지금 히새라는 함수를 실행하면, 안녕 이라는 함수를 제외한 모든 코드가 실행된다.

왜냐하면 안녕 함수를 실행시켜주지 않았기 때문이다.

function 히새() {


    function 안녕() {
    
    }
    안녕()


}

히새()

이렇게 내부에서 안녕 함수를 실행시켜주는 구문을 작성해주어야 히새 함수 실행 시 안녕 함수가 바로 실행될 수 있다.

 

그런데 리액트에서는 우리가 함수를 실행시키는게 아니라 리액트가 알아서 실행한다.

똑똑한 리액트 친구는 히새 안에 있는 함수인 안녕 함수를 히새 함수가 실행된 다음에 실행시킨다.

 

단, 조건이 있다. 함수 이름을 useEffect 로 해줘👸🏻

 

그래서 리액트의 훅 중에 하나인 useEffect 는 "원래" 맨 나중에 실행된다.

상태의 변경이 발생하면 ( 초기 렌더링 또는 리-렌더링 될 때 )

이펙트에 설정된 콜백 함수가 실행된다. 즉, 다음 상태( nextStage ) 에 접근이 가능해진다.

 

useEffect 는 첫 번째 인자로 콜백 함수를 받고 두 번째 인자로 배열을 받는데, 이 배열을 종속성 배열이라고 한다.

종속성 배열이 없는 경우, ( 컴포넌트 렌더링이 될 때마다 ) 이펙트 함수가 항상 실행된다.

종속성 배열을 빈 배열로 작성 시, 컴포넌트 최초 렌더링 시 1회만 실행된다.

종속성 배열에 값을 작성시, 그 state 변수들이 변할 때마다 실행된다.

 

이 종속성 배열 안에 관심사를 작성해주면, 지켜보고 있다가 트리거가 될 때 해당 할 일을 해준다.

종속성 배열은 side effect 가 의존하는 모든 값을 포함해야 한다.

 

UseEffect 는 리액트 컴포넌트의 렌더링에 영향을 미치지 않으면서,

side effect ( 리액트 외부의 것 , fetch, loacalStorage, setTimeout 등 ) 을 사용할 때 사용되는 훅이다.

 


import { useEffect, useState } from 'react';

function LearnStateAndEffects() {
  const [data, setData] = useState(null);
  const [error, setError] = useState(null);
  const [status, setStatus] = useState('pending');

  // side effect
  // server request (endpoint)
  useEffect(() => {
    // 상태 변경
    // 대기 → 로딩 중...
    setStatus('loading');

    // Promise API
    fetch('https://jsonplaceholder.typicode.com/todos?_limit=5')
      // 성공
      .then((response) => response.json())
      .then((responseData) => {
        setData(responseData);
        setStatus('success');
      })
      // 실패
      .catch((error) => {
        // setStatus('error');
        setError(error);
      });
  }, []);

  // 로딩 상태에 따른 조건부 렌더링
  
  // 데이터 가져오는 중(로딩)일 때 표시할 화면
  if (status === 'loading') {
    return (
      <div role="alert">
        <img
          src="https://media2.giphy.com/media/v1.Y2lkPTc5MGI3NjExbXM1MHd1cmZid2plZmF4OW9xbGxyZm5tdXZ2Y2E1czRwZGZ6dDIwaCZlcD12MV9naWZzX3NlYXJjaCZjdD1n/3oEjI6SIIHBdRxXI40/200.gif"
          alt="데이터 가져오는 중입니다."
        />
      </div>
    );
  }

  // 데이터 가져오기 실패한 경우 표시할 화면
  if (status === 'error') {
    <div role="alert">{error.toString()}</div>;
  }

  // 데이터 가져오기 성공했을 때 표시할 화면
  return (
    <div className="m-10 flex flex-col gap-2 items-start">
      <h2 className={`text-indigo-600 font-suit text-2xl`}>
        상태 및 이펙트 학습하기
      </h2>

      {data && (
        <ul>
          {data?.map((item) => (
            <li key={item.id}>{item.title}</li>
          ))}
        </ul>
      )}
    </div>
  );
}

export default LearnStateAndEffects;
import { useEffect, useState } from 'react';

function LearnStateAndEffects() {
  const [data, setData] = useState(null);
  const [error, setError] = useState(null);
  const [status, setStatus] = useState('pending');

	return (
	    <div className="m-10 flex flex-col gap-2 items-start">
	      <h2 className={`text-indigo-600 font-suit text-2xl`}>
	        상태 및 이펙트 학습하기
	      </h2>
          </div>
     );
}

 

처음에는 상태값이 없기 때문에 useState(null) 로 작성해주었다.

데이터, 에러, 상태 3가지로 나눠서 관리해 줄 예정이다.

  return (
    <div className="m-10 flex flex-col gap-2 items-start">
      <h2 className={`text-indigo-600 font-suit text-2xl`}>
        상태 및 이펙트 학습하기
      </h2>

      {data && (
        <ul>
          {data?.map((item) => (
            <li key={item.id}>{item.title}</li>
          ))}
        </ul>
      )}
    </div>
  );
}

통신 상태에 따른 조건부 렌더링에 필요한 jsx 를 작성해주었다.

데이터 값이 없으면 렌더링 하지 않고 데이터 값이 생기면 렌더링을 한다.

  // side effect
  // server request (endpoint)
  useEffect(() => {
    fetch('https://jsonplaceholder.typicode.com/todos?_limit=5')
      // 성공
      .then((response) => response.json())
      .then((responseData) => {
        setData(responseData);
        setStatus('success');
      })
      // 실패
      .catch((error) => {
        // setStatus('error');
        setError(error);
      });
  }, []);

[ 빈 종속성 배열 ] 이 없으면 컴포넌트를 렌더링 할 때마다 서버에 요청한다.

불필요한 서버 요청을 줄이기 위해 [ 빈 종속성 배열 ] 를 꼭 작성해 주어야 한다.

 

서버에 데이터 요청을 한다. side effect 코드인 fetch 를 사용한다. 이 코드는 useEffect 로 감싸줘야 한다. 이게 바로 useEffect 를 사용하는 이유이다. ( 무슨 말일까? )

 

-> useEffect 는 side effect 들을 처리하는 방법을 제공하기 위해 존재한다.

 

side Effect 란?

React 컴포넌트가 화면에 렌더링 된 이후에 비동기로 처리되어야 하는 부수적인 효과들.

함수가 실행되면서 함수 외부에 존재하는 값이나 상태를 변경시키는 등의 행위

 

예시 )

fetch() 메서드 등을 통해 HTTP 통신을 시도하는 것,

Local storage 등에 데이터를 저장하는 것 ,

DOM 을 직접 조작하는 것 ( querySelector. addEventListener ) ,

백엔드 서버에 API 로 데이터 요청하는 것,

브라우저 API 와 상호작용 하는 것,

setTimeout, setInterval 등 에측 불가능한 타이밍 함수 사용

 

 

  // 데이터 가져오는 중(로딩)일 때 표시할 화면
  if (status === 'loading') {
    return (
      <div role="alert">
        <img
          src="https://media2.giphy.com/media/v1.Y2lkPTc5MGI3NjExbXM1MHd1cmZid2plZmF4OW9xbGxyZm5tdXZ2Y2E1czRwZGZ6dDIwaCZlcD12MV9naWZzX3NlYXJjaCZjdD1n/3oEjI6SIIHBdRxXI40/200.gif"
          alt="데이터 가져오는 중입니다."
        />
      </div>
    );
  }

  // 데이터 가져오기 실패한 경우 표시할 화면
  if (status === 'error') {
    <div role="alert">{error.toString()}</div>;
  }

로딩 상태에 따른 조건부 렌더링 코드이다.