Skip to content

Instantly share code, notes, and snippets.

@ohmonster
Last active June 19, 2019 02:45
Show Gist options
  • Select an option

  • Save ohmonster/4dd8b9ef1626ab49e023a23c431eebf9 to your computer and use it in GitHub Desktop.

Select an option

Save ohmonster/4dd8b9ef1626ab49e023a23c431eebf9 to your computer and use it in GitHub Desktop.
import { actions } from './sampleSlice';
import * as api from './api';
import { shouldFetch, ABORTREASONS } from './readyFetchHelpers'
const shouldCallSampleApi = (state, delayMs = 500) => {
let booFetch = true;
if (!state || !state.cart === undefined) {
booFetch = true;
} else {
const fetchStatus = shouldFetch(state.sample.isFetching, state.sample.receivedAt, delayMs);
booFetch = fetchStatus === ABORTREASONS.NO_ABORT;
}
return booFetch;
};
export const getSample = () => {
return async (dispatch, getState) => {
const initialState = getState();
const doFetch = shouldCallSampleApi(initialState);
if (doFetch) {
dispatch(
actions.getSampleSent({ timestamp: new Date().toString(), note: 'initial fetch' })
);
const response = await api.getItems();
const json = await response.json();
if (response.status === 200) {
return dispatch(actions.getSampleSuccess(json));
}
return dispatch(actions.getSampleFailure(json));
}
return Promise.resolve();
};
};
export default getSample;
const ABORTREASONS = {
STILL_FETCHING: 'STILL_FETCHING',
TIME_DELAY: 'TIME_DELAY',
USER_CANCEL: 'USER_CANCEL', //only implemented in certain ES specs. Here to differentiate between a logic abort and a user abort of an XHR
NO_ABORT: 'NO_ABORT',
};
const APIACTIONS = {
REQUEST: 'REQUEST',
SUCCESS: 'SUCCESS',
FAILURE: 'FAILURE',
ABORT: 'ABORT',
};
function propsByActionType(apiActionType) {
switch (apiActionType) {
case APIACTIONS.REQUEST:
return {
isFetching: true,
receivedAt: null,
success: false,
};
case APIACTIONS.SUCCESS:
return {
isFetching: false,
receivedAt: Date.now(),
success: true,
};
case APIACTIONS.FAILURE:
return {
isFetching: false,
receivedAt: Date.now(),
success: false,
};
default:
return {
isfetching: false,
receivedAt: null,
success: true,
};
}
}
const isFetchingProps = (apiActionType = APIACTIONS.REQUEST, state = {}, newObj = {}) => {
const fetchingProps = propsByActionType(apiActionType);
const returnProps = Object.assign({}, state, newObj, fetchingProps);
return returnProps;
};
const shouldFetch = (inProgress = false, lastFetch = 0, delayMs = 500) => {
const now = Date.now();
const timeDiff = now - lastFetch;
if (inProgress) {
return ABORTREASONS.STILL_FETCHING;
}
if (lastFetch !== 0 && timeDiff < delayMs) {
return ABORTREASONS.TIME_DELAY;
}
return ABORTREASONS.NO_ABORT;
};
export { ABORTREASONS, APIACTIONS, shouldFetch, isFetchingProps, propsByActionType };
import { createSlice } from 'redux-starter-kit';
import { propsByActionType, APIACTIONS } from '../../helpers/apiShared';
const sampleSlice = createSlice({
initialState: {},
reducers: {
getSampleSent: (state, action) => {
const fetchProps = propsByActionType(APIACTIONS.REQUEST);
return { ...state, ...fetchProps };
},
getSampleSuccess: (state, action) => {
const sample= action.payload;
const fetchProps = propsByActionType(APIACTIONS.SUCCESS);
return { ...state, ...fetchProps, ...sample};
},
getSampleFailure: (state, action) => {
const error = action.payload;
const fetchProps = propsByActionType(APIACTIONS.FAILURE);
return { ...state, ...fetchProps, error };
},
invalidateSample: (state, action) => {
const fetchProps = propsByActionType();
const newObj = {};
return { newObj, ...fetchProps };
},
},
});
export const { actions, reducer } = sampleSlice;
export default reducer;
import { configureStore } from 'redux-starter-kit';
import reducer as sample from './sampleSlice';
const rootReducer = {
sample,
todos: {}
};
const store = configureStore({
reducer: rootReducer,
preloadedState: initialState,
devTools: true,
});
export default store;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment