Skip to content

Instantly share code, notes, and snippets.

@sebastiandeutsch
Created January 7, 2017 22:59
Show Gist options
  • Save sebastiandeutsch/261e91c638da4ca66b32f16eb81746e3 to your computer and use it in GitHub Desktop.
Save sebastiandeutsch/261e91c638da4ca66b32f16eb81746e3 to your computer and use it in GitHub Desktop.
Compositional Components to fetch data
<SyncStore loader={TeamLoader} loadingComponent={Loading}>
<TeamReaderApp>
<Match exactly pattern="/" component={LinksIndex} />
<Match pattern='/links' component={LinksIndex} />
<Match pattern='/link/new' component={LinkNew} />
<Match pattern='/link/:id/edit' component={LinkEdit} />
<Match pattern='/categories' component={CategoriesIndex} />
<Match pattern='/category/new' component={CategoryNew} />
<Match pattern='/category/:id/edit' component={CategoryEdit} />
</TeamReaderApp>
</SyncStore>;
import _ from 'lodash';
import { LOADED_CATEGORIES } from '../constants/categoryActionTypes';
import { LOADED_LINKS } from '../constants/linkActionTypes';
import * as categoryApi from '../api/categoryApi';
import * as linkApi from '../api/linkApi';
export default class TeamLoader {
needsToSyncStore(params, store) {
const state = store.getState();
const { session } = state.app;
if(session && session.token) {
const { categories } = state;
const { links } = state;
if(Object.values(categories).length > 0 && Object.values(links).length > 0) {
return false;
} else {
return true;
}
} else {
return true;
}
}
syncStore(params, store) {
const { dispatch } = store;
const { session } = store.getState().app;
const promises = [];
if(session) {
const categoiesPromise = categoryApi.getCategories({ session }).then(
(response) => {
dispatch({
type: LOADED_CATEGORIES,
payload: {
...response.data
}
});
}
);
promises.push(categoiesPromise);
const linksPromise = linkApi.getLinks({ session }).then(
(response) => {
dispatch({
type: LOADED_LINKS,
payload: {
...response.data
}
});
}
);
promises.push(linksPromise);
}
return Promise.all(promises);
};
}
import React, { Component, PropTypes } from 'react';
export default class SyncStore extends Component {
static contextTypes = {
"store": PropTypes.shape({
subscribe: PropTypes.func.isRequired,
dispatch: PropTypes.func.isRequired,
getState: PropTypes.func.isRequired
})
}
state = {
storeIsSynchronized: false
}
componentDidMount() {
this.syncStore();
}
componentWillReceiveProps(nextProps) {
this.syncStore();
}
syncStore() {
const loader = new this.props.loader();
if(loader.needsToSyncStore({}, this.context.store)) {
loader.syncStore({}, this.context.store).then(
(response) => {
this.setState({ storeIsSynchronized: true });
},
(error) => {
this.setState({ storeIsSynchronized: false });
}
)
} else {
this.setState({ storeIsSynchronized: true });
}
}
render() {
if(this.state.storeIsSynchronized) {
return (<div>{this.props.children}</div>);
} else {
return React.createElement(this.props.loadingComponent, this.props, this.props.children);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment