Skip to content

Instantly share code, notes, and snippets.

@stevekane
Created December 20, 2013 07:18
Show Gist options
  • Save stevekane/8051456 to your computer and use it in GitHub Desktop.
Save stevekane/8051456 to your computer and use it in GitHub Desktop.
React router example...WIP
var routeManaged = false;
var HashRoutePlugin = {
getCurrentRoute: function() {
return window.location.hash;
},
pushCurrentRoute: function(newRoute) {
window.location.hash = newRoute;
},
setCurrentRoute: function(newRoute) {
window.location.hash.replace(newRoute);
},
listenForChanges: function(cb) {
window.addEventListener('hashchange', cb, false);
},
unlistenForChanges: function(cb) {
window.removeEventListener('hashchange', cb, false);
}
};
var HashLink = React.createClass({
render: function() {
return this.transferPropsTo(<a href={'#' + this.props.href}>{this.props.children}</a>);
}
});
var HistoryRoutePlugin = {
getCurrentRoute: function() {
return window.location.pathname;
},
pushCurrentRoute: function(newRoute) {
window.history.pushState(null, null, newRoute);
},
setCurrentRoute: function(newRoute) {
window.history.replaceState(null, null, newRoute);
},
listenForChanges: function(cb) {
window.addEventListener('popstate', cb, false);
},
unlistenForChanges: function(cb) {
window.removeEventListener('popstate', cb, false);
}
};
var HistoryLink = React.createClass({
handleClick: function(e) {
ROUTER_SINGLETON.routeDidChange(this.props.href);
e.preventDefault();
},
render: function() {
return this.transferPropsTo(
<a href="javascript:;" onClick={this.handleClick}>
{this.props.children}
</a>
);
}
});
// Using hash:
// var RoutePlugin = HashRoutePlugin;
// var Link = HashLink;
// Using history API
var RoutePlugin = HistoryRoutePlugin;
var Link = HistoryLink;
var ROUTER_SINGLETON = null;
var RouterMixin = {
getDefaultProps: function() {
// Make this work on the client or the server
if (typeof window === 'undefined') {
// Running on the server, so initialRoute must be provided.
return {};
}
return {initialRoute: RoutePlugin.getCurrentRoute()};
},
getInitialState: function() {
return {__route: this.props.initialRoute};
},
componentWillReceiveProps: function(nextProps) {
// If initialRoute changes they probably intended for this component
// to reset. TODO: should we warn? Seems like this prop should
// never change.
if (nextProps.initialRoute && this.props.initialRoute !== nextProps.initialRoute) {
this.setState({__route: nextProps.initialRoute});
}
},
componentDidUpdate: function(prevProps, prevState) {
if (this.state.__route !== prevState.__route) {
// We control the route, not the browser.
RoutePlugin.setCurrentRoute(this.state.__route);
}
},
navigate: function(newRoute) {
this.setState({__route: newRoute});
},
getCurrentRoute: function() {
return this.state.__route;
},
__handleRouteChange: function() {
var browserRoute = RoutePlugin.getCurrentRoute();
RoutePlugin.setCurrentRoute(this.state.__route);
this.routeDidChange(RoutePlugin.getCurrentRoute());
},
componentWillMount: function() {
if (routeManaged) {
throw new Error('Route is already managed');
}
routeManaged = true;
if (!this.routeDidChange) {
throw new Error('You must provide a routeDidChange() method.');
}
ROUTER_SINGLETON = this;
},
componentDidMount: function() {
RoutePlugin.setCurrentRoute(this.state.__route);
RoutePlugin.listenForChanges(this.__handleRouteChange);
},
componentWillUnmount: function() {
routeManaged = false;
}
};
var Hello = React.createClass({
mixins: [RouterMixin],
routeDidChange: function(route) {
this.navigate(route);
},
render: function() {
if (this.getCurrentRoute() === '/') {
return <div>Home page <Link href="/test">Go to /test</Link></div>;
} else {
return <div>Test page <Link href="/">Go to /</Link></div>;
}
}
});
React.renderComponent(<Hello initialRoute="/" />, document.body);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment