I have an express server that handles: 1 API route and rendering my initial index.html
to include bundle.js
holding my React/React-Router/Redux application.
As it stands, it is impossible to 404 on my web page as I have a catch all:
app.use(function (req, res) {
return res.render('index')
})
In order for react-router
's NoMatch
to work I need to send a 404 code.
My routes are as follows:
Express — /api/test/:x/:y
React Router — :x/
, :x/:y
What I am essentially trying to achieve is, if the user ever goes to a URL of: :x/:y/z/and/further
then return a 404, unless what they've gone to is /api/test/:x/:y
Questions:
Take a look at react-router server side rendering docs: reacttraining.com/react-router/web/guides/server-rendering
Solution:
match
function from react-router
. It should be written after middlewares that responsible for API routes.So, middleware should be similar to this:
// origin code from https://github.com/reactjs/react-router/blob/master/docs/guides/ServerRendering.md
// this is ES6, but easily can be written on a ES5.
import { match, RouterContext } from 'react-router'
import routes from './routes'
var app = express();
// ...
app.use((req, res, next) => {
match({ routes, location: req.url }, (error, redirectLocation, renderProps) => {
if (error) {
res.status(500).send(error.message)
} else if (redirectLocation) {
res.redirect(302, redirectLocation.pathname + redirectLocation.search)
} else if (renderProps) {
// You can also check renderProps.components or renderProps.routes for
// your "not found" component or route respectively, and send a 404 as
// below, if you're using a catch-all route.
// Here you can prerender component or just send index.html
// For prependering see "renderToString(<RouterContext {...renderProps} />)"
res.status(200).send(...)
} else {
res.status(404).send('Not found')
}
})
});
If any routes change, you don't need to do something on express app, because you're using same code for frontend and backend.