Created
February 1, 2017 17:53
-
-
Save penx/f11b3301a2b692129ee035b7a44476de to your computer and use it in GitHub Desktop.
This file contains hidden or 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
/** | |
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