Created
December 20, 2013 07:18
-
-
Save stevekane/8051456 to your computer and use it in GitHub Desktop.
React router example...WIP
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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