Skip to content

Instantly share code, notes, and snippets.

@ryanflorence
Last active December 8, 2019 07:34
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ryanflorence/21ce8cb052eebbe7dac3 to your computer and use it in GitHub Desktop.
Save ryanflorence/21ce8cb052eebbe7dac3 to your computer and use it in GitHub Desktop.
/** @jsx React.DOM */
function pushUrl(path) {
location.hash = path;
}
function toArray(maybeArray) {
return Array.isArray(maybeArray) ? maybeArray : [maybeArray];
}
function childrenArray(component) {
return component.props.children ? toArray(component.props.children) : [];
}
function matchedChildRoute(path, component) {
var children = childrenArray(component);
for (var i = 0, l = children.length; i < l; i ++) {
if (children[i].props.path === path) {
return children[i];
}
if (children[i].props.children) {
var matchedGrandbaby= matchedChildRoute(path, children[i]);
if (matchedGrandbaby) {
return children[i];
}
}
}
return false;
}
var Link = React.createClass({
handleClick: function(event) {
event.preventDefault();
var path = this.props.to;
pushUrl(path);
},
render: function() {
return (
<a href={this.props.to} onClick={this.handleClick}>{this.props.children}</a>
);
}
});
var Routed = {
getInitialState: function() {
return {activeChild: null};
},
componentWillMount: function(path) {
this.handleRouteChange();
window.addEventListener('hashchange', this.handleRouteChange, false);
},
componentWillUnmount: function() {
window.removeEventListener('hashchange', this.handleRouteChange);
},
handleRouteChange: function() {
var path = location.hash.substr(1);
var matched = matchedChildRoute(path, this)
this.setState({activeChild: matched});
},
outlet: function() {
var children = this.props.children;
if (!children) throw new Error("you don't have any children, why are you calling outlet()?");
return this.state.activeChild;
}
};
/******************************************/
// app stuff
var App = React.createClass({
mixins: [Routed],
render: function() {
return (
<Root>
<Index path="/"/>
<About path="/about">
<AboutIndex path="/about/"/>
<Company path="/about/company"/>
<Contact path="/contact"/>
</About>
<Users path="/users/"/>
</Root>
);
}
});
var Root = React.createClass({
mixins: [Routed],
render: function() {
return (
<div className="Root">
<ul>
<li><Link to="/">Home</Link></li>
<li><Link to="/about/">About</Link></li>
<li><Link to="/users/">Users</Link></li>
</ul>
{this.outlet()}
</div>
);
}
});
var Index = React.createClass({
mixins: [Routed],
render: function() {
return (
<div className="Index">
<h1>Index</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
</div>
);
}
});
var AboutIndex = React.createClass({
mixins: [Routed],
render: function() {
return (
<div className="Index">
<h1>About Index</h1>
<p>Consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
</div>
);
}
});
var About = React.createClass({
mixins: [Routed],
render: function() {
return (
<div className="About">
<h1>About</h1>
<ul>
<li><Link to="/about/company">Company</Link></li>
<li><Link to="/contact">Contact</Link></li>
</ul>
{this.outlet()}
</div>
);
}
});
var Company = React.createClass({
mixins: [Routed],
render: function() {
return <div className="Company"><h2>Company</h2></div>;
}
});
var Contact = React.createClass({
mixins: [Routed],
render: function() {
return <div className="About"><h2>Contact</h2></div>;
}
});
var Users = React.createClass({
mixins: [Routed],
statics: {
cache: null
},
getInitialState: function() {
return {users: Users.cache || []};
},
componentDidMount: function() {
var url = 'http://addressbook-api.herokuapp.com/contacts';
if (!Users.cache) {
$.getJSON(url).then(function(res) {
Users.cache = res.contacts;
this.setState({users: res.contacts});
}.bind(this));
}
},
render: function() {
var users = this.state.users.map(function(user) {
return <div>{user.first} {user.last}</div>;
});
var content = !users.length ? 'Loading users...' : users;
return <div className="Users">{content}</div>;
}
});
React.renderComponent(<App/>, document.body);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment