Skip to content

Instantly share code, notes, and snippets.

@penx
Created February 1, 2017 17:53
Show Gist options
  • Save penx/f11b3301a2b692129ee035b7a44476de to your computer and use it in GitHub Desktop.
Save penx/f11b3301a2b692129ee035b7a44476de to your computer and use it in GitHub Desktop.
/**
Example usage of React Router 4 to handle:
- Known routes to render a specific component, e.g. /
- An array of valid top level slugs, e.g. /:pageId
- A dictionary of top level slugs that should redirect, e.g. /:redirectId
- An array of valid slugs for a known subroute, e.g. /items/:itemId
- 404 for anything that is not handled, including invalid slugs, with a correct http response
- Server side example, but ReactApp is written so that routing would work universally
**/
import { createServer } from 'http'
import express from 'express'
import React, { PropTypes } from 'react'
import { renderToString } from 'react-dom/server'
import { StaticRouter, Route, Switch, Redirect } from 'react-router-dom'
const app = express();
const pages = ['page-one', 'page-two']
const items = ['item-one', 'item-two']
const redirects = {
'redirect-one': '/item/item-one',
'redirect-two': '/page-one',
'redirect-three': '/invalid-slug',
'redirect-four': '//google.com'
}
const Item = () => {
return <h2>This is a valid item</h2>
}
class NotFound extends React.Component {
componentWillMount() {
if(this.context.router.staticContext) {
// running on the server, so specify response status
// TODO: this might not be the right place to bubble data up to Express
this.context.router.staticContext.status = 404
}
}
render() {
return <h2>404</h2>
}
}
NotFound.contextTypes = {
router: PropTypes.shape({
staticContext: PropTypes.object
}).isRequired
}
const ReactApp = () => (<div>
<h1>Routing POC</h1>
<Switch>
<Route exact path="/">
<h2>Home</h2>
</Route>
<Route path="/item/:itemId" render={({match: {params: {itemId}}}) => {
if(items.includes(itemId)) {
return <Item />
} else {
return <NotFound />
}
}} />
<Route path="/:topLevelSlug" render={({match: {params: {topLevelSlug}}}) => {
if(pages.includes(topLevelSlug)) {
return <h2>This is a valid page: {topLevelSlug}</h2>
} else if(redirects[topLevelSlug]) {
return <Redirect to={redirects[topLevelSlug]}/>
} else {
return <NotFound />
}
}}/>
<Route component={NotFound} />
</Switch>
</div>)
app.get('*', function(req, res, next) {
const context = {};
console.log(req.url)
const html = renderToString(
<StaticRouter location={req.url} context={context}><ReactApp /></StaticRouter>
);
if(context.status) {
res.status(context.status)
}
if (context.url) {
res.writeHead(302, {
Location: context.url
})
res.end()
} else {
res.send(html);
}
});
createServer(app).listen(8008)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment