Last active
December 8, 2023 13:51
-
-
Save michaelmcshinsky/2560d9494b241afce230d9c6f5de6448 to your computer and use it in GitHub Desktop.
A comprehensive starter solution to making API calls structured and manageable in code architecture and development teams.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import apiProvider from './provider'; | |
export class ApiCore { | |
constructor(options) { | |
if (options.getAll) { | |
this.getAll = () => { | |
return apiProvider.getAll(options.url); | |
}; | |
} | |
if (options.getSingle) { | |
this.getSingle = (id) => { | |
return apiProvider.getSingle(options.url, id); | |
}; | |
} | |
if (options.post) { | |
this.post = (model) => { | |
return apiProvider.post(options.url, model); | |
}; | |
} | |
if (options.put) { | |
this.put = (model) => { | |
return apiProvider.put(options.url, model); | |
}; | |
} | |
if (options.patch) { | |
this.patch = (model) => { | |
return apiProvider.patch(options.url, model); | |
}; | |
} | |
if (options.remove) { | |
this.remove = (id) => { | |
return apiProvider.remove(options.url, id); | |
}; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import axios from 'axios'; | |
import { handleResponse, handleError } from './response'; | |
// Define your api url from any source. | |
// Pulling from your .env file when on the server or from localhost when locally | |
const BASE_URL = 'http://127.0.0.1:3333/api/v1'; | |
/** @param {string} resource */ | |
const getAll = (resource) => { | |
return axios | |
.get(`${BASE_URL}/${resource}`) | |
.then(handleResponse) | |
.catch(handleError); | |
}; | |
/** @param {string} resource */ | |
/** @param {string} id */ | |
const getSingle = (resource, id) => { | |
return axios | |
.get(`${BASE_URL}/${resource}/${id}`) | |
.then(handleResponse) | |
.catch(handleError); | |
}; | |
/** @param {string} resource */ | |
/** @param {object} model */ | |
const post = (resource, model) => { | |
return axios | |
.post(`${BASE_URL}/${resource}`, model) | |
.then(handleResponse) | |
.catch(handleError); | |
}; | |
/** @param {string} resource */ | |
/** @param {object} model */ | |
const put = (resource, model) => { | |
return axios | |
.put(`${BASE_URL}/${resource}`, model) | |
.then(handleResponse) | |
.catch(handleError); | |
}; | |
/** @param {string} resource */ | |
/** @param {object} model */ | |
const patch = (resource, model) => { | |
return axios | |
.patch(`${BASE_URL}/${resource}`, model) | |
.then(handleResponse) | |
.catch(handleError); | |
}; | |
/** @param {string} resource */ | |
/** @param {string} id */ | |
const remove = (resource, id) => { | |
return axios | |
.delete(`${BASE_URL}/${resource}`, id) | |
.then(handleResponse) | |
.catch(handleError); | |
}; | |
export const apiProvider = { | |
getAll, | |
getSingle, | |
post, | |
put, | |
patch, | |
remove, | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export function handleResponse(response) { | |
if (response.results) { | |
return response.results; | |
} | |
if (response.data) { | |
return response.data; | |
} | |
return response; | |
} | |
export function handleError(error) { | |
if (error.data) { | |
return error.data; | |
} | |
return error; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const url = 'tasks'; | |
const plural = 'tasks'; | |
const single = 'task'; | |
// plural and single may be used for message logic if needed in the ApiCore class. | |
const apiTasks = new ApiCore({ | |
getAll: true, | |
getSingle: true, | |
post: true, | |
put: false, | |
patch: true, | |
delete: false, | |
url: url, | |
plural: plural, | |
single: single | |
}); | |
apiTasks.massUpdate = () => { | |
// Add custom api call logic here | |
} | |
export apiTasks; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, { useEffect } from 'react'; | |
import { apiTasks } from '@/services/api'; | |
export function Tasks() { | |
const [tasks, setTasks] = useState([]); | |
useEffect(() => { | |
_getTasks(); | |
}, []); | |
function _getTasks() { | |
apiTasks.getAll().then((res) => { | |
let arr = _parseTasks(res.results.data); | |
setTasks(arr); | |
}); | |
} | |
function _parseTasks(tasks) { | |
return tasks.map((task) => { | |
// Parse task information | |
return task; | |
}); | |
} | |
function _createTask(task) { | |
apiTasks.post(task).then((res) => { | |
// state logic | |
}); | |
} | |
function _updateTask(task) { | |
apiTasks.patch(task).then((res) => { | |
// state logic | |
}); | |
} | |
function _removeTask(id) { | |
apiTasks.remove(id).then((res) => { | |
// state logic | |
}); | |
} | |
return ( | |
<ul> | |
{tasks.map((task) => ( | |
<li key={task.id}>{task.name}</li> | |
))} | |
</ul> | |
); | |
} |
Hi Michael, Thanks for the quick response. I have created a simple react app which fetches list of users and displays it. I have used the above 'api-provider.js' and 'response.js' files to create a service layer. Here When i make a get call to get all the users. I see that the log inside 'then' block is seen.
fetchItems = () => { return apiProvider.getAll(url).then(function (userData) { console.log('inside then block'); // Control reaches here return userData; }).catch((error)=>{ console.log('inside catch block'); }); };
I am returning 400 error code in my back end. Also the catch block of getAll() function is getting called.
/** @param {string} resource */ const getAll = (resource) => { return axios .get(`${BASE_URL}/${resource}`) .then(handleResponse) .catch(handleError); // Control reaches here };
Is this the expected behaviour ? How do I make sure that the catch block in the fetchItems function gets called and it does not go inside then?
Looks like this is a feature of the Axios library. You'll probably have to implement your own interceptor for axios or a check to throw certain statuses to your .catch method.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
That is normally an issue with the server, not the JavaScript. Most likely your server is sending back incorrect status codes.