Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 17 additions & 4 deletions client/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { createElement } from 'react'
import ReactDOM from 'react-dom'
import { EventEmitter } from 'events'
import HeadManager from './head-manager'
import { rehydrate } from '../lib/css'
import { createRouter } from '../lib/router'
Expand Down Expand Up @@ -33,13 +34,16 @@ const headManager = new HeadManager()
const container = document.getElementById('__next')

export default (onError) => {
const emitter = new EventEmitter()
if (ids && ids.length) rehydrate(ids)

router.subscribe(({ Component, props, err }) => {
render({ Component, props, err }, onError)
render({ Component, props, err, emitter }, onError)
})

render({ Component, props, err }, onError)
render({ Component, props, err, emitter }, onError)

return emitter
}

export async function render (props, onError = renderErrorComponent) {
Expand All @@ -56,7 +60,7 @@ async function renderErrorComponent (err) {
await doRender({ Component: ErrorComponent, props, err })
}

async function doRender ({ Component, props, err }) {
async function doRender ({ Component, props, err, emitter }) {
if (!props && Component &&
Component !== ErrorComponent &&
lastAppProps.Component === ErrorComponent) {
Expand All @@ -65,10 +69,19 @@ async function doRender ({ Component, props, err }) {
props = await loadGetInitialProps(Component, { err, pathname, query })
}

if (emitter) {
emitter.emit('before-reactdom-render', { Component })
}

Component = Component || lastAppProps.Component
props = props || lastAppProps.props

const appProps = { Component, props, err, router, headManager }
lastAppProps = appProps
ReactDOM.render(createElement(App, appProps), container)

if (emitter) {
emitter.emit('after-reactdom-render', { Component })
}

lastAppProps = appProps
}
30 changes: 28 additions & 2 deletions client/next-dev.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import patch from './patch-react'
import evalScript from '../lib/eval-script'

const { __NEXT_DATA__: { errorComponent } } = window
const ErrorComponent = evalScript(errorComponent).default

// apply patch first
patch((err) => {
Expand All @@ -13,10 +17,32 @@ require('react-hot-loader/patch')

const next = window.next = require('./')

next.default(onError)
const emitter = next.default(onError)

function onError (err) {
// just show the debug screen but don't render ErrorComponent
// so that the current component doesn't lose props
next.render({ err })
next.render({ err, emitter })
}

let lastScroll

emitter.on('before-reactdom-render', ({ Component }) => {
// Remember scroll when ErrorComponent is being rendered to later restore it
if (!lastScroll && Component === ErrorComponent) {
const { pageXOffset, pageYOffset } = window
lastScroll = {
x: pageXOffset,
y: pageYOffset
}
}
})

emitter.on('after-reactdom-render', ({ Component }) => {
if (lastScroll && Component !== ErrorComponent) {
// Restore scroll after ErrorComponent was replaced with a page component by HMR
const { x, y } = lastScroll
window.scroll(x, y)
lastScroll = null
}
})