Skip to content

Instantly share code, notes, and snippets.

@ryanflorence
Created November 8, 2014 18:52
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ryanflorence/88fcecf09cad60438cfe to your computer and use it in GitHub Desktop.
Save ryanflorence/88fcecf09cad60438cfe to your computer and use it in GitHub Desktop.
/** @jsx React.DOM */
var React = require('react');
var Router = require('react-router');
var whenKeys = require('when/keys');
var EventEmitter = require('events').EventEmitter;
var { Route, DefaultRoute, NotFoundRoute, ActiveRouteHandler } = Router;
var { Link, Navigation, ActiveState } = Router;
var API = 'http://addressbook-api.herokuapp.com';
var loadingEvents = new EventEmitter();
var App = React.createClass({
statics: {
fetchData (params) {
return getJSON(`${API}/contacts`).then((res) => res.contacts);
}
},
getInitialState () {
return { loading: false };
},
componentDidMount () {
loadingEvents.on('loadstart',() => this.setState({loading: true}));
loadingEvents.on('loadend', () => this.setState({loading: false}));
},
renderContacts () {
return this.props.data.contacts.map((contact) => {
return (
<li>
<Link to="contact" params={contact}>{contact.first} {contact.last}</Link>
</li>
);
});
},
render () {
return (
<div className={this.state.loading ? 'loading' : ''}>
<ul>
{this.renderContacts()}
</ul>
<ActiveRouteHandler {...this.props}/>
</div>
);
}
});
var Contact = React.createClass({
statics: {
fetchData (params) {
return getJSON(`${API}/contacts/${params.id}`).then((res) => res.contact);
}
},
render () {
var { contact } = this.props.data;
return (
<div>
<h1>{contact.first} {contact.last}</h1>
<img key={contact.avatar} src={contact.avatar}/>
</div>
);
}
});
var routes = (
<Route name="contacts" path="/" handler={App}>
<Route name="contact" path="contact/:id" handler={Contact}/>
</Route>
);
Router.run(routes, function (Handler, state) {
// problem here is that this emits, but all the contexts have changed for `Handler`
// so rerenders aren't correct, need an event or something before we do any work
// in the router
loadingEvents.emit('loadstart');
fetchData(state.matches, state.activeParams).then((data) => {
React.render(<Handler data={data} />, document.getElementById('example'), function() {
loadingEvents.emit('loadend');
});
});
});
function fetchData(matches, params) {
return whenKeys.all(matches.filter((match) => {
return match.route.handler.fetchData;
}).reduce((data, match) => {
var {name, handler} = match.route;
data[name] = handler.fetchData(params);
return data;
}, {}));
}
function getJSON(url) {
return new Promise((resolve, reject) => {
var req = new XMLHttpRequest();
req.onload = function () {
if (req.status === 404) {
reject(new Error('not found'));
} else {
resolve(JSON.parse(req.response));
}
};
req.open('GET', url);
req.send();
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment