Skip to content

Instantly share code, notes, and snippets.

@gitumarkk
Last active August 21, 2019 06:28
Show Gist options
  • Select an option

  • Save gitumarkk/5a86f66af52f59b8a5d70b8657247591 to your computer and use it in GitHub Desktop.

Select an option

Save gitumarkk/5a86f66af52f59b8a5d70b8657247591 to your computer and use it in GitHub Desktop.
/*********** redux/api.js ***********/
class ReduxApi {
constructor(appName, relativePath) {
this.APP_NAME = appName;
this.URL = `{relativePath}`
this.GET_REQUEST = `${this.APP_NAME}/GET_REQUEST`;
this.GET_SUCCESS = `${this.APP_NAME}/GET_SUCCESS`;
this.GET_ERROR = `${this.APP_NAME}/GET_ERROR`;
this.reducer = this.reducer.bind(this);
this.selectGlobal = this.selectGlobal.bind(this);
this.makeSelectBase = this.makeSelectBase.bind(this);
this.saga = this.saga.bind(this);
this.get = this.get.bind(this);
}
getRequest() {
return {
type: this.GET_REQUEST
};
}
getSuccess(data) {
return {
type: this.GET_SUCCESS,
data
};
}
getError(data) {
return {
type: this.GET_ERROR,
data
};
}
getRequestReducerHandler(state, action) {
return state
.set('requesting', true);
}
getSuccessReducerHandler(state, action) {
return state
.set('requesting', false)
.set('initialized', true)
.set('list', action.data);
}
getErrorReducerHandler(state, action) {
return state
.set('error', action.error)
.set('requesting', false);
}
/*
*
* NOT INCLUDING GET (detail), POST, PUT, DELETE or PATCH, for sake of berivity
*
*/
reducer(state = fromJS({ list: [],
detail: {},
requesting: false,
initialized: false,
}), action) {
switch (action.type) {
case this.GET_REQUEST: {
return getRequestReducerHandler(state, action);
}
case this.GET_SUCCESS: {
return getSuccessReducerHandler(state, action)
}
case this.GET_ERROR: {
return getErrorReducerHandler(state, action)
}
default:
return state;
}
}
* get(action = {}) {
try {
// Call using the request helper
const resp = yield Axios.get(action.url || this.URL);
yield put(this.getSuccess(resp.data, action.append));
} catch (err) {
yield put(this.getError(err));
}
}
// Saga
* saga() {
yield all([
takeLatest(this.GET_REQUEST, this.get),
]);
}
// Selectors
selectGlobal(state) {
return state.get(this.APP_NAME);
}
/*
* Key corresponds to the redux state keys e.g. list, detail, etc.
*/
makeSelectBase = (key) => {
return createSelector(
this.selectGlobal,
(globalState) => globalState.get(key)
);
}
}
export default ReduxApi;
/*********** redux/index.js ***********/
import { all } from 'redux-saga/effects';
import ReduxAPI from './api';
const user = new ReduxAPI('user', '/api/v1/user/');
const feed = new ReduxAPI('feed', '/api/v1/feed/');
const comment = new ReduxAPI('comment', '/api/v1/comment/');
export default {
user: user.reducer,
feed: board.feed,
comment: dance.comment
};
export function* saga() {
yield all([
user.saga(),
feed.saga(),
comment.saga()
]);
}
/*********** container/component.js ***********/
import React from 'react';
import { createStructuredSelector } from 'reselect';
import { connect } from 'react-redux';
// App
import ReduxApi from 'containers/redux/api';
const user = new ReduxApi('user', '/api/v1/user/');
const feed = new ReduxAPI('feed', '/api/v1/feed/');
class Header extends React.Component {
constructor(props) {
super(props);
this.props.getUser();
this.props.getFeed();
}
render() {
const { currentUser, currentFeed } = this.props;
return (
<div className={classes.root}>
{ currentUser && currentUser.username}
{ currentFeed && currentFeed.length}
</div>
);
}
}
const mapDispatchToProps = (dispatch) => ({
getUser: () => dispatch(user.getRequest()),
getFeed: () => dispatch(feed.getRequest())
});
const mapStateToProps = createStructuredSelector({
currentUser: user.makeSelectBase('list'),
currentFeed: feed.makeSelectBase('list')
});
export default connect(
mapStateToProps,
mapDispatchToProps
)(Header));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment