Skip to content

Instantly share code, notes, and snippets.

@laere
Forked from l0gicgate/FetchActionCreators.js
Created March 14, 2016 18:28
Show Gist options
  • Save laere/875113be5c2af13a8c83 to your computer and use it in GitHub Desktop.
Save laere/875113be5c2af13a8c83 to your computer and use it in GitHub Desktop.
Reusable action creators / reducers.
import axios from 'axios';
class FetchActionCreators {
constructor(endpoint, actions) {
const [REQUEST, SUCCESS, FAILURE] = actions;
this.actions = {
REQUEST,
SUCCESS,
FAILURE,
};
this.endpoint = endpoint;
}
fetch() {
return (dispatch) => {
dispatch(this.request());
return APIRequest.get(this.endpoint)
.then(res => {
dispatch(this.receive(this.actions.SUCCESS, res.data));
})
.catch((res) => {
dispatch(this.receive(this.actions.FAILURE));
});
};
}
request() {
return {
type: this.actions.REQUEST,
};
}
receive(type, data) {
return {
type,
data,
};
}
}
export default FetchActionCreators;
class FetchReducerPrototype {
static initialState = {
data: null,
fetching: false,
receivedAt: null,
};
constructor({ actions }) {
this.actions = actions;
return this.reducer;
}
reducer = (state = FetchReducerPrototype.initialState, action = {}) => {
switch (action.type) {
case this.actions.REQUEST:
return Object.assign({}, state, {
fetching: true,
});
case this.actions.SUCCESS:
return Object.assign({}, state, {
data: action.data,
fetching: false,
receivedAt: Date.now(),
});
case this.actions.FAILURE:
return Object.assign({}, state, {
fetching: false,
});
default:
return state;
}
}
}
export default FetchReducerPrototype;
import { combineReducers } from 'redux';
import StreamsReducer from './StreamsReducer';
import VideosReducer from './VideosReducer';
const rootReducer = combineReducers({
streams: StreamsReducer,
videos: VideosReducer,
});
import React, { PropTypes } from 'react';
import { streamsFetchActions } from './StreamsReducer';
class StreamsContainer extends React.Component {
static propTypes = {
dispatch: PropTypes.func.isRequired,
streams: PropTypes.object.isRequired,
};
componentDidMount() {
const { dispatch, streams } = this.props;
if (!streams.fetching && !streams.data) {
dispatch(streamsFetchActions.fetch());
}
}
render() {
const { streams } = this.props;
return streams.fetching ?
<div>Loading...</div> :
<div>{/* access streams via streams.data */}</div>;
}
}
function mapStateToProps(state) {
return {
streams: state.streams,
}
}
export default connect(mapStateToProps)(StreamsContainer);
import FetchActionCreators from './FetchReducerPrototype';
import FetchReducerPrototype from './FetchReducerPrototype';
const REQUEST_STREAMS = 'REQUEST_STREAMS';
const RECEIVE_STREAMS_SUCCESS = 'RECEIVE_STREAMS_SUCCESS';
const RECEIVE_STREAMS_FAILURE = 'RECEIVE_STREAMS_FAILURE';
export const streamsFetchActions = new FetchActionCreators(
'http://yourwebsite.com/streams',
[
REQUEST_STREAMS,
RECEIVE_STREAMS_SUCCESS,
RECEIVE_STREAMS_FAILURE,
]
);
export default new FetchReducerPrototype(streamsFetchActions);
import FetchActionCreators from './FetchReducerPrototype';
import FetchReducerPrototype from './FetchReducerPrototype';
const REQUEST_VIDEOS = 'REQUEST_VIDEOS';
const RECEIVE_VIDEOS_SUCCESS = 'RECEIVE_VIDEOS_SUCCESS';
const RECEIVE_VIDEOS_FAILURE = 'RECEIVE_VIDEOS_FAILURE';
export const videosFetchActions = new FetchActionCreators(
'http://yourwebsite.com/videos',
[
REQUEST_VIDEOS,
RECEIVE_VIDEOS_SUCCESS,
RECEIVE_VIDEOS_FAILURE,
]
);
export default new FetchReducerPrototype(videosFetchActions);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment