[React] Axios 사용하기

Jenny·2023년 4월 13일
2

React

목록 보기
1/3
post-thumbnail

기본 메서드

GET : 데이터 조회 axios.get(url[, config])
POST : 데이터 등록 axios.post(url, data[, config])
PUT : 데이터 수정 axios.put(url, data[, config])
DELETE : 데이터 제거 axios.delete(url[, config])

사용법

1) axios(config)

  • config 설정을 axios()에 전달하여 요청
  • url 속성만 필수이며 나머지 속성은 옵션
  • method가 지정되지 않으면 GET으로 기본 설정됨

2) 기본 Params

  • Method
  • Url
  • Data (optional)
  • Params (optional)

axios.get()

  • 사용상황에 따라 params: {} 객체가 존재할지 안할지가 결정된다.

1) 단순 데이터(페이지 요청, 지정된 요청) 요청을 수행할 경우 > params 필요 없음

// callback 을 사용할 때,
axios.get("url")
    .then(response =>  {
         // response  
    }).catch(error => {
        // 오류발생시 실행
    }).then(() => {
        // 항상 실행
    });


// async await 함수를 사용할 때, 
try {
	const data = await axios.get("url");
} catch {
	// 오류 발생시 실행
}
});

2) 파라미터 데이터를 포함시키는 경우 (사용자 번호에 따른 조회)

axios.get("url", {
        params: {
          	id: 123
        }
    })
    .then(response => {
         // response  
    }).catch(error => {
        // 오류발생시 실행
    }).then(() => {
        // 항상 실행
    });
   
   
// async await 함수를 사용할 때, 
try {
	const data = await axios.get("url", 
         params: { 
			id: 123 
		 }
    );
} catch {
	// 오류 발생시 실행
}

axios.post()

  • post 메서드에는 일반적으로 데이터를 Message Body에 포함시켜서 보냄
  • get 메서드에서 params를 사용한 경우와 비슷하게 수행된다.
axios.post("url", {
         username: "",
         password: ""
    })
    .then(response => {
         // response  
    }).catch(error => {
        // 오류발생시 실행
    }).then(() => {
        // 항상 실행
    });
    

// async await 함수를 사용할 때, 
try {
	const data = await axios.post("url");
} catch {
	// 오류 발생시 실행
}

axios.put()

  • put 메서드는 서버 내부적으로 get ➔ post 과정을 거치기 때문에 post 메서드와 비슷한 형태임
axios.put("url", {
         username: "",
         password: ""
    })
    .then(response => {
         // response  
    }).catch(error => {
        // 오류발생시 실행
    }).then(() => {
        // 항상 실행
    });


// async await 함수를 사용할 때, 
try {
	const data = await axios.put("url", { 	
      	 username: "", 
         password: ""
    });
} catch {
	// 오류 발생시 실행
}

axios.delete()

  • delete 메서드에는 일반적으로 body가 비어있음
  • 그래서 형태는 get과 비슷한 형태를 띄지만 한 번 delete 메서드가 서버에 들어가게 된다면 서버 내에서 삭제 process를 진행하게 된다.
axios.delete('/user?ID=12345')
  .then(response => {
      // handle success
      console.log(response);
  })
  .catch(error => {
      // handle error
      console.log(error);
  })
  .then(() => {
      // always executed
  });
 

// async await 함수를 사용할 때, 
try {
	const data = await axios.delete("url");
} catch {
	// 오류 발생시 실행
}

많은 데이터를 요청할 경우

query나 params가 많아져서 헤더에 많은 정보를 담을 수 없을 때는 두 번째 인자에 data를 추가해줄 수 있다.

axios.delete('/user?ID=12345',{
      data: {
        post_id: 1,
        comment_id: 5,
        username: "april"
      }
})
  .then(response => {
      // handle success
      console.log(response);
  })
  .catch(error => {
      // handle error
      console.log(error);
  })
  .then(() => {
      // always executed
  });
 

// async await 함수를 사용할 때, 
try {
	const data = await axios.delete("url");
} catch {
	// 오류 발생시 실행
}

React에서 Axios 사용하기

보통 프로젝트에서는
API의 스펙, 서버의 주소, credentials 설정을 담당하는 API.js 라는 파일 생성 -> axios 의 기본 설정에 대해서 지정 -> 각각의 서비스에서 가져가 사용하는 형태로 구현.

1) axios 의 인스턴스 생성/async await 통신

먼저 axios 의 인스턴스를 생성해서 API라는 변수에 담고 API를 반환시킨다.

// API.js
// axios 의 인스턴스를 생성
import axios from 'axios';

const API = axios.create({
	BASE_URL: '',
    headers: {
      	'Content-Type': 'application/json',
    },
    withCredentials: true,
});

export default API;

2) 각각 파일에서는 async await 으로 콜백을 처리하여 통신한다.

import API from '../utils/API';

export const login = async (code) => {
    const { data } = await API.post('url',
          JSON.stringify(code)
    );
    return data;
}

3) Error Handling을 위한 try-catch문 사용

import API from '../utils/API';

export const refresh = async () => {
    try {
        const { data } = await API.get('url');
    	return data;
    } catch {
    	// Error Handling
    }
};

useState로 요청 관리하기

요청에 대한 상태를 관리하기 위해서는 3가지 상태를 관리해줘야함.
1. 요청의 결과 (data)
2. 로딩 상태 (loading)
3. 에러 (error)

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

function Users() {
  const [users, setUsers] = useState(null);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState(null);

  const fetchUsers = async () => {
    try {
      // 요청이 시작 할 때에는 error 와 users 를 초기화하고
      setError(null);
      setUsers(null);
      // loading 상태를 true 로 바꿉니다.
      setLoading(true);
      const response = await axios.get(
        'https://jsonplaceholder.typicode.com/users'
      );
      setUsers(response.data); // 데이터는 response.data 안에 들어있습니다.
    } catch (e) {
      setError(e);
    }
    setLoading(false);
  };

  useEffect(() => {
    fetchUsers();
  }, []);

  if (loading) return <div>로딩중..</div>; 
  if (error) return <div>에러가 발생했습니다</div>;

	// 아직 users가 받아와 지지 않았을 때는 아무것도 표시되지 않도록 해줍니다.
  if (!users) return null;

	// 드디어 users가 성공적으로 받아와 진 상태입니다.
  return (
		<>
	    <ul>
	      {users.map(user => (
	        <li key={user.id}>
	          {user.username} ({user.name})
	        </li>
	      ))}
	    </ul>
			// button을 클릭하면 API를 다시 불러와줍니다.
			<button onClick={ fetchUsers }>다시 불러오기<button>
		</>
  );
}

export default Users;

useReducer로 요청 관리하기

useReducer로 관리할 때의 장점

  • 로직의 재사용이 가능하다.
  • 컴포넌트 내부의 코드가 짧아진다. (but, reducer 함수의 추가로 전체적인 코드의 길이는 늘어남.)

reducer 작성하기

function reducer(state, action) {
  switch (action.type) {
		// 발생할 수 있는 상황 LOADING, SUCCESS, ERROR에 대한 case를 만들어 줍니다.
		// 로딩중 상태 업데이트
    case 'LOADING':
      return {
        loading: true,
        data: null,
        error: null
      };
		// 불러오는데에 성공했을 때는 action.data를 저장해줍니다.
    case 'SUCCESS':
      return {
        loading: false,
        data: action.data,
        error: null
      };
		// 에러가 발생하면 action.error를 전달해주겠습니다.
    case 'ERROR':
      return {
        loading: false,
        data: null,
        error: action.error
      };
    default:
      throw new Error(`Unhandled action type: ${action.type}`);
  }

useReducer 사용하기

function Users() {
	// reducer 함수의 전달과 초기상태를 정의합니다.
  const [state, dispatch] = useReducer(reducer, {
    loading: false,
    data: null,
    error: null
  });

  const fetchUsers = async () => {
		//시작할 때 로딩중인 상태를 만들어줍니다.
    dispatch({ type: 'LOADING' });
    try {
      const response = await axios.get(
        'https://jsonplaceholder.typicode.com/users'
      );
      dispatch({ type: 'SUCCESS', data: response.data });
    } catch (e) {
      dispatch({ type: 'ERROR', error: e });
    }
  };

  useEffect(() => {
    fetchUsers();
  }, []);

  // state.data 를 users 키워드로 조회
  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>
      <button onClick={fetchUsers}>다시 불러오기</button>
    </>
  );
}

axios Interceptors

  • Axios 라이브러리 이용해서 서버에 Rest API 요청을 보내거나 응답을 받는 과정에서 가로채어 일을 처리할 수 있게 해줌
import axios from 'axios';

const onFulfilled = (response) => {
    // HTTP status가 2XX일 때 처리하고 싶은 로직이 있다면 여기에서 처리함
		// 데이터 받기에 성공했으므로 받은 response를 그대로 return 해준다.
		// 물론 따로 가공해도 됩니다.
    return response;
};
const onRejected = (error) => {
    // HTTP status가 2XX이 아닐 때 여기를 통과하게 됨
    // return은 항상 Promise.reject(error)로 해야함
    return Promise.reject(error);
};
axios.interceptors.response.use(onFulfilled, onRejected);
import axios from 'axios';
const customAxiosInstance = () => {
    const axiosInstance = axios.create();
    const onFulfilled = (response) => response;
    const retry = (errorConfig) => {
        return new Promise((resolve) => {
            setTimeout(() => {
                console.log('retry');
                resolve(axiosInstance.request(errorConfig));
            }, 5000);
        });
    }
    const onRejected = (error) => {
        if (error.config) {
            return retry(error.config);
        }
        
        return Promise.reject(error);
    };
    axiosInstance.interceptors.response.use(
        onFulfilled,
        onRejected,
    );
    return axiosInstance;
};
try {
    const apiRequest = customAxiosInstance();
    const response = await apiRequest.get(API_URL);
} catch {
}

참고
참고
https://react.vlpt.us/integrate-api/01-basic.html

profile
Developer로의 여정

0개의 댓글