Skip to content

Latest commit

 

History

History
238 lines (173 loc) · 5.1 KB

README_KO.md

File metadata and controls

238 lines (173 loc) · 5.1 KB

EasyFetch

React+Axios에 익숙해져 있는 상태에서 attraction 팀프로젝트에서 Next.js App router 사용하다보니 몇가지 불편함을 접했습니다.

  • 클라이언트 컴포넌트에서 interceptor 기능의 부재
  • res.json(), JSON.stringify을 매번 사용하는 것
  • 400번 이상의 에러는 res.ok로 분기 처리
  • fetch에서는 사용할 수 없는 axios.post와 같은 API 메서드

위와 같은 불편한 사항들을 해결하기 위해 Easyfetch는 Next App router에서 사용하는 확장된 fetch를 axios 사용자들이 좀 더 편리하게 사용하기 위해 만든 라이브러리 입니다.

설치

pnpm add @woogie0303/easyfetch
yarn add @woogie0303/easyfetch
npm install @woogie0303/easyfetch

타입

RequestInitWithNextConfig

interface NextFetchRequestConfig {
  revalidate?: number | false;
  tags?: string[];
}

interface RequestInitWithNextConfig extends globalThis.RequestInit {
  next?: NextFetchRequestConfig | undefined;
}

EasyFetchResponse

type EasyFetchResponse<T> = Omit<
  Awaited<ReturnType<typeof fetch>>,
  keyof Body | 'clone' | 'url'
> & {
  body: T;
  config: [string | URL, RequestInit | RequestInitWithNextConfig | undefined];
};

EasyFetchRequestType

type EasyFetchRequestType = [
  string | URL,
  RequestInitWithNextConfig | undefined
];

특징

header와 baseUrl을 설정 할 수 있습니다.

easyFetch()

const easy = easyFetch(defaultConfig);

Parameter

defaultConfig?: {
  baseUrl?: string | URL;
  headers?: HeadersInit;
}

api method 및 기존 fetch 인자인 Request 인스턴스를 사용할 수 있습니다.

const easy = easyFetch({
  baseUrl: 'https://attraction/',
  headers: {
    'Content-Type': 'multipart/form-data',
  },
});

const request = new Request('https://hi');

easy.request(request);

easy.get('getUser');
easy.delete('deleteUser');

easy.patch('postUser', { userData: 'kang' });
easy.post('postUser', { userData: 'kang' });
easy.put('postUser', { userData: 'kang' });

Parameter, Return Type

get, delete method
<T>(url: string | URL, reqConfig?: Omit<RequestInitWithNextConfig, 'method'>) =>
  Promise<EasyFetchResponse<T>>;
patch, post, put method
<T>(
  url: string | URL,
  reqBody?: object, // Request Body
  reqConfig?: Omit<RequestInitWithNextConfig, 'method' | 'body'>
) => Promise<EasyFetchResponse<T>>;
request method
<T>(request: RequestInfo | URL, requestInit?: RequestInitWithNextConfig) =>
  Promise<EasyFetchResponse<T>>;

Request Interceptor

요청을 보내기 전에 Fetch 인자와 관련해서 설정할 것이 있으면 추가할 수 있는 기능입니다.

const easy = easyFetch();

easy.interceptor.request(onFulfilled, onReject);

Parameter, Return Type

 (
  onFulfilled?: (arg: EasyFetchRequestType)
    => | Promise<EasyFetchRequestType>
       | EasyFetchRequestType,
  onRejected?: (err: any) => any
 ): void

Response Interceptor

응답을 받기전에 처리해야할 로직을 설정할 수 있습니다. 400번대 에러를 처리할때는 EasyFetchResponse 타입 단언을 사용해서 서버 에러를 핸들링 할 수 있습니다.

const easy = easyFetch();

easy.interceptor.response(onFulfilled, onReject);

Parameter, Return Type

 (
  onFulfilled?: (arg: EasyFetchResponse<any>)
    => | Promise<EasyFetchResponse<any>>
       | EasyFetchResponse<any>,
  onRejected?: (err: any) => any
 ): void

400대 서버 에러처리

const easy = easyFetch();

easy.interceptor.response(
  (res) => res,
  async (err) => {
    const error = err as EasyFetchResponse<ErrorType>;

    if (error.status === 401) {
      const { body } = await easy.get<Token>('https://google.co/getToken', {
        ...error.config[1],
      });

      const headers = new Headers(error.config[1]?.headers);

      headers.set('Authorization', `Bearer ${body.accessToken}`);

      return easy.request(error.config[0], {
        ...error.config[1],
        headers,
      });
    }

    throw err;
  }
);

주의

에러를 핸들링할 때 Interceptor Response기능은 response의 형태를 바꿔주는 transform response와 다른 기능입니다. error config url을 인자로 해서 반환해주는 것이 타입의 일관성을 줄 수 있습니다.

// 잘못된 사용 예시
const easy = easyFetch();
easy.interceptor.response(
  (res) => res,
  (err) => {
    const serverError = err as EasyFetchResponse<ResponseType>;

    return { data: 'Hi' };
  }
);

const data = await easy.get<ResponseType>('https://sdf'); // return {data: 'Hi'}

// 올바른 사용 예시
const easy = easyFetch();
easy.interceptor.response(
  (res) => res,
  (err) => {
    const serverError = err as EasyFetchResponse<ResponseType>;
    const [url, requestConfig] = serverError.config;

    return easy.get(url, requestConfig);
  }
);

const data = easy.get<ResponseType>('https://sdf'); // return ResponseType Data

라이센스

MIT © DongWook Kang