11import React , { Component } from "react"
2- import PropTypes from "prop-types"
32import ReactDOM from "react-dom"
43import { connect , Provider } from "react-redux"
54import omit from "lodash/omit"
65
76const SystemWrapper = ( getSystem , ComponentToWrap ) => class extends Component {
87 render ( ) {
9- return < ComponentToWrap { ...getSystem ( ) } { ...this . props } { ...this . context } />
8+ return < ComponentToWrap { ...getSystem ( ) } { ...this . props } { ...this . context } />
109 }
1110}
1211
13- const RootWrapper = ( reduxStore , ComponentToWrap ) => class extends Component {
12+ const RootWrapper = ( getSystem , reduxStore , ComponentToWrap ) => class extends Component {
1413 render ( ) {
14+ const { getComponent } = getSystem ( )
15+ const ErrorBoundary = getComponent ( "ErrorBoundary" , true )
16+
1517 return (
1618 < Provider store = { reduxStore } >
17- < ComponentToWrap { ...this . props } { ...this . context } />
19+ < ErrorBoundary targetName = { ComponentToWrap ?. name } >
20+ < ComponentToWrap { ...this . props } { ...this . context } />
21+ </ ErrorBoundary >
1822 </ Provider >
1923 )
2024 }
@@ -30,7 +34,7 @@ const makeContainer = (getSystem, component, reduxStore) => {
3034 let wrappedWithSystem = SystemWrapper ( getSystem , component , reduxStore )
3135 let connected = connect ( mapStateToProps ) ( wrappedWithSystem )
3236 if ( reduxStore )
33- return RootWrapper ( reduxStore , connected )
37+ return RootWrapper ( getSystem , reduxStore , connected )
3438 return connected
3539}
3640
@@ -66,73 +70,43 @@ export const makeMappedContainer = (getSystem, getStore, memGetComponent, getCom
6670}
6771
6872export const render = ( getSystem , getStore , getComponent , getComponents , domNode ) => {
69- let App = ( getComponent ( getSystem , getStore , getComponents , "App" , "root" ) )
70- ReactDOM . render ( ( < App /> ) , domNode )
73+ let App = getComponent ( getSystem , getStore , getComponents , "App" , "root" )
74+ ReactDOM . render ( < App /> , domNode )
7175}
7276
73- class ErrorBoundary extends Component {
74- constructor ( props ) {
75- super ( props )
76- this . state = { hasError : false , error : null }
77- }
78-
79- static getDerivedStateFromError ( error ) {
80- return { hasError : true , error }
81- }
82-
83- componentDidCatch ( error , errorInfo ) {
84- console . error ( error , errorInfo ) // eslint-disable-line no-console
85- }
86-
77+ /**
78+ * Creates a class component from a stateless one and wrap it with Error Boundary
79+ * to handle errors coming from a stateless component.
80+ */
81+ const createClass = ( getSystem , OriginalComponent ) => class extends Component {
8782 render ( ) {
88- if ( this . state . hasError ) {
89- return < Fallback name = { this . props . targetName } />
90- }
83+ const { getComponent } = getSystem ( )
84+ const ErrorBoundary = getComponent ( "ErrorBoundary" )
9185
92- return this . props . children
93- }
94- }
95- ErrorBoundary . propTypes = {
96- targetName : PropTypes . string ,
97- children : PropTypes . oneOfType ( [
98- PropTypes . arrayOf ( PropTypes . node ) ,
99- PropTypes . node ,
100- ] )
101- }
102- ErrorBoundary . defaultProps = {
103- targetName : "this component" ,
104- children : null ,
105- }
106-
107- const Fallback = ( { name } ) => (
108- < div className = "fallback" >
109- 😱 < i > Could not render { name === "t" ? "this component" : name } , see the console.</ i >
110- </ div >
111- )
112- Fallback . propTypes = {
113- name : PropTypes . string . isRequired ,
114- }
115-
116- // Render try/catch wrapper
117- const createClass = OriginalComponent => class extends Component {
118- render ( ) {
11986 return (
120- < ErrorBoundary targetName = { OriginalComponent ?. name } >
87+ < ErrorBoundary targetName = { OriginalComponent ?. name } getComponent = { getComponent } >
12188 < OriginalComponent { ...this . props } />
12289 </ ErrorBoundary >
12390 )
12491 }
12592}
12693
127- const wrapRender = ( component ) => {
94+ const wrapRender = ( getSystem , component ) => {
12895 const isStateless = component => ! ( component . prototype && component . prototype . isReactComponent )
129- const target = isStateless ( component ) ? createClass ( component ) : component
96+ const target = isStateless ( component ) ? createClass ( getSystem , component ) : component
13097 const { render : oriRender } = target . prototype
13198
99+ /**
100+ * This render method override handles errors that are throw in render method
101+ * of class components.
102+ */
132103 target . prototype . render = function render ( ...args ) {
133104 try {
134105 return oriRender . apply ( this , args )
135106 } catch ( error ) {
107+ const { getComponent } = getSystem ( )
108+ const Fallback = getComponent ( "Fallback" )
109+
136110 console . error ( error ) // eslint-disable-line no-console
137111 return < Fallback name = { target . name } />
138112 }
@@ -159,11 +133,11 @@ export const getComponent = (getSystem, getStore, getComponents, componentName,
159133 }
160134
161135 if ( ! container )
162- return wrapRender ( component )
136+ return wrapRender ( getSystem , component )
163137
164138 if ( container === "root" )
165139 return makeContainer ( getSystem , component , getStore ( ) )
166140
167141 // container == truthy
168- return makeContainer ( getSystem , wrapRender ( component ) )
142+ return makeContainer ( getSystem , wrapRender ( getSystem , component ) )
169143}
0 commit comments