-
-
Save michaelmcshinsky/2560d9494b241afce230d9c6f5de6448 to your computer and use it in GitHub Desktop.
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); | |
}; | |
} | |
} | |
} |
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, | |
}; |
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; | |
} |
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; |
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> | |
); | |
} |
task-api-example.js has one. You can add your axios logic there.
For both success and failure cases, It is reaching .then() in all the calling places. Do we need a interceptor to return Promise.reject(error) ?
That is normally an issue with the server, not the JavaScript. Most likely your server is sending back incorrect status codes.
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.
up