11import React , { Component , PropTypes } from 'react'
22import { AppContainer } from 'react-hot-loader'
3+ import shallowEquals from './shallow-equals'
34import { warn } from './utils'
45
6+ const ErrorDebug = process . env . NODE_ENV === 'production'
7+ ? null : require ( './error-debug' ) . default
8+
59export default class App extends Component {
610 static childContextTypes = {
7- router : PropTypes . object ,
811 headManager : PropTypes . object
912 }
1013
11- constructor ( props ) {
12- super ( props )
13- this . state = propsToState ( props )
14- this . close = null
15- }
16-
17- componentWillReceiveProps ( nextProps ) {
18- const state = propsToState ( nextProps )
19- try {
20- this . setState ( state )
21- } catch ( err ) {
22- this . handleError ( err )
23- }
14+ getChildContext ( ) {
15+ const { headManager } = this . props
16+ return { headManager }
2417 }
2518
26- componentDidMount ( ) {
27- const { router } = this . props
28-
29- this . close = router . subscribe ( ( data ) => {
30- const props = data . props || this . state . props
31- const state = propsToState ( {
32- ...data ,
33- props,
34- router
35- } )
19+ render ( ) {
20+ const { Component, props, err, router } = this . props
21+ const containerProps = { Component, props, router }
3622
37- try {
38- this . setState ( state )
39- } catch ( err ) {
40- this . handleError ( err )
41- }
42- } )
23+ return < div >
24+ < Container { ...containerProps } />
25+ { ErrorDebug && err ? < ErrorDebug err = { err } /> : null }
26+ </ div >
4327 }
4428
45- componentWillUnmount ( ) {
46- if ( this . close ) this . close ( )
47- }
29+ }
4830
49- getChildContext ( ) {
50- const { router, headManager } = this . props
51- return { router, headManager }
31+ class Container extends Component {
32+ shouldComponentUpdate ( nextProps ) {
33+ // need this check not to rerender component which has already thrown an error
34+ return ! shallowEquals ( this . props , nextProps )
5235 }
5336
5437 render ( ) {
55- const { Component, props } = this . state
38+ const { Component, props, router } = this . props
39+ const url = createUrl ( router )
5640
41+ // includes AppContainer which bypasses shouldComponentUpdate method
42+ // https://github.com/gaearon/react-hot-loader/issues/442
5743 return < AppContainer >
58- < Component { ...props } />
44+ < Component { ...props } url = { url } />
5945 </ AppContainer >
6046 }
61-
62- async handleError ( err ) {
63- console . error ( err )
64-
65- const { router, ErrorComponent } = this . props
66- const { pathname, query } = router
67- const props = await ErrorComponent . getInitialProps ( { err, pathname, query } )
68- const state = propsToState ( { Component : ErrorComponent , props, router } )
69-
70- try {
71- this . setState ( state )
72- } catch ( err2 ) {
73- console . error ( err2 )
74- }
75- }
7647}
7748
78- function propsToState ( props ) {
79- const { Component, router } = props
80- const url = {
49+ function createUrl ( router ) {
50+ return {
8151 query : router . query ,
8252 pathname : router . pathname ,
8353 back : ( ) => router . back ( ) ,
@@ -98,9 +68,4 @@ function propsToState (props) {
9868 return router . replace ( replaceRoute , replaceUrl )
9969 }
10070 }
101-
102- return {
103- Component,
104- props : { ...props . props , url }
105- }
10671}
0 commit comments