We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
안녕하세요, Nextjs를 공부하다 블로그에 작성해주신 return-fetch 에 대한 게시글을 보고 프로젝트에 적용해보던 중,
return-fetch
문의 사항이 생겨 이슈 남깁니다.
아래와 같이 코드를 작성해보았는데, queryParams 와 requestBody 는 접근이 불가능 하더라구요.
queryParams
requestBody
제가 최종적으로 사용하고자 하는 코드는
// use request example const response = await request<void>({ method: 'put', url: '/members/vehicles/me', requestBody: body, }); return response?.data;
이런 식으로 사용하고싶은데, 어떻게 코드를 작성해야 할까요 ? 아래는 제가 작성한 코드입니다 !
import returnFetch, { ReturnFetch, FetchArgs, ReturnFetchDefaultOptions, } from 'return-fetch'; import { get, set } from 'lodash'; import qs from 'qs'; import { useCustomerStore } from '@/store/customer'; import { RequestParams } from './types'; import logger from '@/utils/logger'; // req body를 json으로 받고, res body를 json으로 반환하는 fetch type JsonRequestInit = Omit<NonNullable<FetchArgs[1]>, 'body'> & { body?: object; queryParams?: Record<string, unknown>; }; export type ResponseGenericBody<T> = Omit< Awaited<ReturnType<typeof fetch>>, keyof Body | 'clone' > & { body: T; }; export type JsonResponse<T> = T extends object ? ResponseGenericBody<T> : ResponseGenericBody<unknown>; const parseJsonSafely = (text: string): object | string => { try { return JSON.parse(text); } catch (e) { if ((e as Error).name !== 'SyntaxError') { throw e; } return text.trim(); } }; export const returnFetchJson = (args?: ReturnFetchDefaultOptions) => { const fetch = returnFetch(args); return async <T>( url: FetchArgs[0], init?: JsonRequestInit ): Promise<JsonResponse<T>> => { const response = await fetch(url, { ...init, body: init?.body && JSON.stringify(init.body), }); const body = parseJsonSafely(await response.text()) as T; return { headers: response.headers, ok: response.ok, redirected: response.redirected, status: response.status, statusText: response.statusText, type: response.type, url: response.url, body, } as JsonResponse<T>; }; }; // reposne가 400이상의 status를 받는 경우 에러 throw const returnFetchThrowingErrorByStatusCode: ReturnFetch = (args) => returnFetch({ ...args, interceptors: { response: async (response) => { if (response.status >= 400) { throw await response.text().then(Error); } return response; }, }, }); export const client = returnFetchJson({ fetch: returnFetchThrowingErrorByStatusCode({ baseUrl: process.env.NEXT_PUBLIC_API_URL, headers: { Accept: 'application/json' }, querySerializer: (queryParams) => { return qs.stringify(queryParams, { arrayFormat: 'brackets' }); }, interceptors: { request: async (requestArgs) => { const [url, init] = requestArgs; logger('--- Request 시작 ---'); logger(`> Request url: ', ${url}`); logger(`> Request: ', ${init}`); const { authorization } = useCustomerStore.getState(); logger(`> Authorization: ', ${authorization}`); if (authorization) { logger('> Set Authorization: ', authorization); set(requestArgs, 'headers.authorization', authorization); } set(requestArgs, 'headers.service-name', 'CUSTOMER_APP'); logger('--- Request 종료 ---'); return requestArgs; }, response: async (response, requestArgs) => { const { headers, url, status, statusText } = response; const [_, requestInit] = requestArgs; const apiUrl = `${process.env.NEXT_PUBLIC_API_URL}${url}`; const authorization = get(headers, 'authorization'); logger('--- Response 시작 ---'); if (authorization) { logger('## Save authorization via response: ', authorization); useCustomerStore.getState().saveAuthorization(authorization); } logger(`< Response [${requestInit?.method}]: ${apiUrl}`); logger(`< Response [${status}]: ${statusText ?? ''}`); logger(`< Response Headers: ${JSON.stringify(headers)}`); logger(response); logger('--- Response 종료 ---'); return response; }, }, }), }); const fetchResponseOnRejected = (error: Error) => { const method = get(error, 'config.method'); const url = `${process.env.NEXT_PUBLIC_API_URL}${get(error, 'config.url')}`; logger(`< Response Error [${method}]: ${url}`); logger(`< Response Error: `, JSON.stringify(get(error, 'response.error'))); if (get(error, 'response.status') === 403) { useCustomerStore.getState().clearCustomer(); } logger('--- Response 에러 ---'); return Promise.reject(error); }; export const request = async <T>({ method, url, queryParams, requestBody, isMultipart, }: RequestParams) => { let headers = {}; if (isMultipart) { headers = { 'Content-Type': 'multipart/form-data', }; } switch (method) { case 'get': return client(url, { method, headers, queryParams }).catch( fetchResponseOnRejected ); case 'post': return client(url, { method, headers, requestBody, queryParams }).catch( fetchResponseOnRejected ); case 'put': return client(url, { method, headers, requestBody, queryParams }).catch( fetchResponseOnRejected ); case 'delete': return client(url, { method, headers, requustBody }).catch( fetchResponseOnRejected ); default: return Promise.reject(new Error('Invalid method')); } };
The text was updated successfully, but these errors were encountered:
@H0onnn 안녕하세요!
fetch는 axios와 다르게 query parameter를 별도의 파라미터로 처리하지 않고 url 뒤에 ?a=b 형태로 사용합니다 (보통의 URL에서 보던 query parameter와 동일함)
?a=b
코드를 보니 returnFetchJson의 첫 번째 매개변수에 querySerializer property를 넣으셨는데, querySerializer는 라이브러리에서 지원하지 않는 parameter라서 아무 의미가 없을 것 같네요.
returnFetchJson
querySerializer
코드 마지막의 request 함수에서 queryParams를 serialize해서 url 뒤에 붙여주면 될 것 같습니다.
request
Sorry, something went wrong.
No branches or pull requests
안녕하세요, Nextjs를 공부하다 블로그에 작성해주신
return-fetch
에 대한 게시글을 보고 프로젝트에 적용해보던 중,문의 사항이 생겨 이슈 남깁니다.
아래와 같이 코드를 작성해보았는데,
queryParams
와requestBody
는 접근이 불가능 하더라구요.제가 최종적으로 사용하고자 하는 코드는
이런 식으로 사용하고싶은데, 어떻게 코드를 작성해야 할까요 ? 아래는 제가 작성한 코드입니다 !
The text was updated successfully, but these errors were encountered: