A simple wrapper around the fetch
API.
This is a placeholder repo for a pattern I find myself recreating every time I start a new application.
Nearly every client-side app needs to make HTTP requests, but using fetch
directly isn't seamless -- you have to turn the Response
object into something useful, and response codes > 2xx don't throw. Plus you will almost always benefit from having a centralized place to make HTTP requests so it's easier to add logging, custom request headers, etc.
The createClient()
factory function returns an object with the HTTP verbs as methods (.get()
, .post()
, etc.). That returned object can then be used as the HTTP layer to interact with any given data source.
Typically I'll pass the HTTP client object to another module used for making API calls.
// src/api/http.js
export const http = createClient({
baseURL:
process.env.NODE_ENV === 'production'
? 'http://www.my-api.com'
: 'http://dev.my-api.com',
fetch: window.fetch,
requestInterceptors: [
async (request) => {
const authToken = await getAuthToken();
return {
...request,
headers: {
...request.headers,
authorization: `Bearer ${authToken}`,
},
};
},
],
errorListeners: [
(response) => {
if (response instanceof Error) {
return;
}
captureErrorMetric(response);
},
],
});
// src/api/plant-api.js
import { http } from './http';
const plantApiFactory = (http) => {
return {
all: () => http.get('/plants'),
find: (id) => http.get(`/plants/${id}`),
create: (plant) =>
http.post('/plants', {
plant,
}),
};
};
export const plantApi = plantApiFactory(http);