Skip to content

Instantly share code, notes, and snippets.

@murilomothsin
Created June 17, 2019 18:51
Show Gist options
  • Save murilomothsin/d11a707a70f06482a0b40dede7a2eed2 to your computer and use it in GitHub Desktop.
Save murilomothsin/d11a707a70f06482a0b40dede7a2eed2 to your computer and use it in GitHub Desktop.
import 'regenerator-runtime/runtime';
import { getToken, getCompany } from '../reducers/auth';
export class ApiError extends Error {
constructor(status, body) {
super(`ApiError: ${status}. ${JSON.stringify(body)}`);
this.status = status;
this.body = body;
}
}
export default function Api(state) {
return {
login,
fetchProduct,
};
function login(body) {
return request('/sign_in', { body, method: 'post' });
}
function fetchProduct(id) {
return request(`/products/${id}`, { method: 'get' });
}
function request(path, {
method,
headers,
body,
...config
}) {
const BASE_URL = 'http://localhost:3000';
if (method === 'GET' && body) {
path = [path, toQuery(body)].join('?');
body = undefined;
} else {
body = JSON.stringify(body);
}
return fetch(`${BASE_URL}${path}`, {
method,
body,
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
'Accept-Language': 'en',
Authorization: `Bearer ${getToken(state)}`,
'X-User-Company': getCompany(state),
...headers,
},
...config,
}).then((response) => {
if (!response.ok) { throw response; }
return response.json();
});
}
// TODO: use query-string
function toQuery(obj) {
if (!obj) { return ''; }
return Object.entries(obj).map(([key, val]) => `${key}=${val}`).join('&');
}
}
import Api, { ApiError } from './api';
import {
FETCH_PRODUCT,
} from '../actions/types';
import { fetchProductSuccess } from '../actions'
import { takeLatest, call, put, select, apply } from 'redux-saga/effects';
function* api(method, ...args) {
try {
const apiInstance = Api(yield select());
const response = yield apply(apiInstance, method, args);
return response;
} catch (err) {
const body = yield err.json();
if (err.status === 401) {
yield put(logout());
} else {
throw new ApiError(err.status, body);
}
}
return null;
}
function* fetchProduct(action) {
try {
let data = yield call(api, 'fetchProduct', action.payload);
yield put(fetchProductSuccess(data))
} catch (e) {
// catch error on a bad fetch call
// alert using an alert library
}
}
export function* productSaga() {
yield takeLatest(FETCH_PRODUCT, fetchProduct);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment