Skip to content

Commit e527098

Browse files
impronunciablerauchg
authored andcommitted
Implemented missing pieces for overriding 404 and 500 pages. (#10)
1 parent a932171 commit e527098

File tree

4 files changed

+25
-4
lines changed

4 files changed

+25
-4
lines changed

Readme.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,17 @@ Each top-level component receives a `url` property with the following API:
139139
- `pushTo(url)` - performs a `pushState` call that renders the new `url`. This is equivalent to following a `<Link>`
140140
- `replaceTo(url)` - performs a `replaceState` call that renders the new `url`
141141

142+
### Error handling
143+
144+
404 or 500 errors are handled both client and server side by a default component `error.js`. If you wish to override it, define a `_error.js`:
145+
146+
```jsx
147+
import React from 'react'
148+
export default ({ statusCode }) => (
149+
<p>An error { statusCode } occurred</p>
150+
)
151+
```
152+
142153
### Production deployment
143154

144155
To deploy, run:
@@ -169,7 +180,6 @@ For example, to deploy with `now` a `package.json` like follows is recommended:
169180
The following tasks are planned and part of our roadmap
170181

171182
- [ ] Add option to supply a `req`, `res` handling function for custom routing
172-
- [ ] Add option to supply a custom error component to render 404, 500 pages
173183
- [ ] Add option to extend or replace custom babel configuration
174184
- [ ] Add option to extend or replace custom webpack configuration
175185
- [ ] Investigate pluggable component-oriented rendering backends (Inferno, Preact, etc)

lib/router.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,13 @@ export default class Router {
149149
const cancel = () => { cancelled = true }
150150
this.componentLoadCancel = cancel
151151

152-
const props = await (Component.getInitialProps ? Component.getInitialProps(ctx) : {})
152+
let props = {}
153+
const status = ctx.xhr.status
154+
if (status === 404 || status === 500) {
155+
props = { statusCode: ctx.xhr.status }
156+
} else {
157+
props = await (Component.getInitialProps ? Component.getInitialProps(ctx) : {})
158+
}
153159

154160
if (cancel === this.componentLoadCancel) {
155161
this.componentLoadCancel = null

server/build/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ export default async function build (dir) {
88
const templateDir = resolve(__dirname, '..', '..', 'lib', 'pages')
99

1010
// create `.next/pages/_error.js`
11-
// which may be overwriten by the user sciprt, `pages/_error.js`
11+
// which may be overwriten by the user script, `pages/_error.js`
1212
const templatPaths = await glob('**/*.js', { cwd: templateDir })
1313
await Promise.all(templatPaths.map(async (p) => {
1414
await transpile(resolve(templateDir, p), resolve(dstDir, 'pages', p))

server/render.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ export async function render (url, ctx = {}, {
2121
const mod = require(p)
2222
const Component = mod.default || mod
2323

24-
const props = await (Component.getInitialProps ? Component.getInitialProps(ctx) : {})
24+
const { err, res } = ctx
25+
const props = ctx.err ? getErrorProps(ctx, dev) : await (Component.getInitialProps ? Component.getInitialProps(ctx) : {})
2526
const component = await read(resolve(dir, '.next', '_bundles', 'pages', path))
2627

2728
const { html, css } = StyleSheetServer.renderStatic(() => {
@@ -62,3 +63,7 @@ export async function renderJSON (url, { dir = process.cwd() } = {}) {
6263
function getPath (url) {
6364
return parse(url || '/').pathname.slice(1).replace(/\.json$/, '')
6465
}
66+
67+
function getErrorProps (ctx, dev) {
68+
return { statusCode: ctx.res.statusCode, stacktrace: dev ? ctx.err.message : undefined }
69+
}

0 commit comments

Comments
 (0)