본문 바로가기

React

API 연동하기 (useState, useEffect, useReducer)

반응형

컴포넌트에서 api 요청하는 가장 기본적인 방법은

- useState와 useEffect로 데이터 로딩하기

or - useReducer로 데이터 로딩하기 

 

사용 라이브러리

- axios

 

아래 상태를 관리하게 된다.

1. 요청의 결과

2. 로딩상태

3. 에러

 

1. useState로 데이터 받아오기

 

import React, { useState, useEffect } from "react";
import axios from "axios";

function Users() {
  //결과물, 1. 요청의 결과
  const [users, setUsers] = useState(null);
  // API가 요청 중인지 아닌지, 2. 로딩상태
  const [loading, setLoading] = useState(false);
  //error, 3. 에러
  const [error, setError] = useState(null);

  useEffect(() => {
    const fetchUsers = async () => {
      try {
        setUsers(null);
        setError(null);
        setLoading(true); //로딩시작
        const response = await axios.get(
          "http://jsonplaceholder.typicode.com/users"
        );
        setUsers(response.data); //데이터 받아오고 setUser에 담기
      } catch (e) {
        setError(e); //에러가 발생한 경우
      }
      setLoading(false); //로딩이 끝났다는 것을 확인
    };
    fetchUsers();
  }, []);

  if (loading) return <div>로딩중...</div>;
  if (error) return <div>에러 발생</div>;
  if (!users) return null;

  return (
    <ul>
      {users.map((user) => (
        <li key={user.id}>
          {user.username} ({user.name})
        </li>
      ))}
    </ul>
  );
}

export default Users;

 

 

2. useReducer로 데이터 받아오기 

 

import React, { useEffect, useReducer } from "react";
import axios from "axios";

//loading, success, error
function reducer(state, action) {
  switch (action.type) {
    case "LOADING":
      return {
        loading: true,
        data: null,
        error: null,
      };
    case "SUCCESS":
      return {
        loading: false,
        data: action.data,
        error: null,
      };
    case "ERROR":
      return {
        loading: false,
        data: null,
        error: action.error,
      };
    default:
      //return state;
      throw new Error(`Unhandled action type: ${action.type}`);
  }
}

function UsersReducer() {
  const [state, dispatch] = useReducer(reducer, {
    loading: false,
    data: null,
    error: null,
  });

  const fetchUsers = async () => {
    dispatch({ type: "LOADING" });
    try {
      const response = await axios.get(
        "http://jsonplaceholder.typicode.com/users"
      );
      dispatch({ type: "SUCCESS", data: response.data });
    } catch (e) {
      dispatch({ type: "ERROR", error: e });
    }
  };
  useEffect(() => {
    fetchUsers();
  }, []);

  const { loading, data: users, error } = state;

  if (loading) return <div>로딩중...</div>;
  if (error) return <div>에러 발생</div>;
  if (!users) return null;

  return (
    <ul>
      {users.map((user) => (
        <li key={user.id}>
          {user.username} ({user.name})
        </li>
      ))}
    </ul>
  );
}

export default UsersReducer;

 

- useState보다 코드 길이는 길어지지만, reducer만 파일을 분리해서 다른 컴포넌트 사용시 재사용이 가능하다. (VScode에서 우클릭 refactor)