Using v4 declarative routing with SSR, I need a way of sending a 404 when my app renders a NotFound route. I know it is pretty easy to accomplish if you define all your routes in one object - just use matchPath to iterate the routes and check for a match. But could not find any example of this behavior when using the declarative routing approach.
I played around and found a way of accomplishing this by mutating the staticContext object. Not sure if it's a hacky or clean solution 馃槃 Is there a different approach that is preferred?
Posting code here if someone is having the same question.
// App.js
...
<Switch>
<Route exact path="/" component={Home}/>
<Route path="/page" component={Page}/>
<Route component={NotFound} />
</Switch>
...
// NotFound.js
export default class NotFound extends Component {
static contextTypes = {
router: PropTypes.object
}
render() {
const { router } = this.context;
// Tell server we should send a 404 not found
if (router.staticContext) {
router.staticContext.statusCode = 404;
}
return <h1>Not Found</h1>
}
}
```js
// server.js
app.get('*', (req, res) => {
const context = {};
const app = (
);
// render app to string, inject into html
// html = ...
const status = context.statusCode || 200;
res.status(status).send(html);
});
The only change that I would make is to set the status code in componentWillMount.
For a more reusable approach, you could create a component whose sole purpose is to set the status code (i.e., <Status code>)
Yes, @hampusohlsson you've got the right idea. The staticContext object is the same one that you provide to <StaticRouter context> so you can mutate it to pass whatever you want back to the rendering process.
FYI to those that may stumble on this closed issue, the staticContext now lives underneath the history context.
@ctrlplusb Thanks for the note. I'm wondering though: is that the best place for it? Maybe it should still live under context.router ... this stuff hasn't finalized yet.
I would prefer context.router myself, having it in history doesn't feel intuitive to me. 馃榾
it's been a little more than a year and now staticContext is under props
Most helpful comment
The only change that I would make is to set the status code in
componentWillMount.For a more reusable approach, you could create a component whose sole purpose is to set the status code (i.e.,
<Status code>)