diff --git a/commonjs/asyncComponent.js b/commonjs/asyncComponent.js
index 4b06f8d..6ac5aca 100644
--- a/commonjs/asyncComponent.js
+++ b/commonjs/asyncComponent.js
@@ -221,19 +221,19 @@ function asyncComponent(config) {
module = _state.module,
error = _state.error;
+
+ if (error) {
+ return ErrorComponent ? _react2.default.createElement(ErrorComponent, _extends({}, this.props, { error: error })) : null;
+ }
+
// This is as workaround for React Hot Loader support. When using
// RHL the local component reference will be killed by any change
// to the component, this will be our signal to know that we need to
// re-resolve it.
-
if (sharedState.module == null && !this.resolving && typeof window !== 'undefined') {
this.resolveModule();
}
- if (error) {
- return ErrorComponent ? _react2.default.createElement(ErrorComponent, _extends({}, this.props, { error: error })) : null;
- }
-
var Component = es6Resolve(module);
return Component ? _react2.default.createElement(Component, this.props) : LoadingComponent ? _react2.default.createElement(LoadingComponent, this.props) : null;
}
diff --git a/src/__tests__/__snapshots__/asyncComponent.test.js.snap b/src/__tests__/__snapshots__/asyncComponent.test.js.snap
new file mode 100644
index 0000000..e090dbe
--- /dev/null
+++ b/src/__tests__/__snapshots__/asyncComponent.test.js.snap
@@ -0,0 +1,25 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`asyncComponent in a browser environment when an error occurs resolving a component should render the ErrorComponent 1`] = `
+
+
+
+ failed to resolve
+
+
+
+`;
+
+exports[`asyncComponent in a server environment when an error occurs resolving a component should render the ErrorComponent 1`] = `
+
+
+
+ failed to resolve
+
+
+
+`;
diff --git a/src/__tests__/asyncComponent.test.js b/src/__tests__/asyncComponent.test.js
index 1efa1fd..b83b370 100644
--- a/src/__tests__/asyncComponent.test.js
+++ b/src/__tests__/asyncComponent.test.js
@@ -22,4 +22,63 @@ describe('asyncComponent', () => {
setTimeout(resolve, resolveDelay + 10),
).then(() => expect(setStateSpy.callCount).toEqual(1))
})
+
+ describe('in a browser environment', () => {
+ let oldWindow
+ beforeAll(() => {
+ oldWindow = window
+ global.window = {}
+ })
+ afterAll(() => {
+ global.window = oldWindow
+ })
+ describe('when an error occurs resolving a component', () => {
+ it.only('should render the ErrorComponent', () => {
+ const resolveDelay = 10
+ const Bob = asyncComponent({
+ resolve: () =>
+ new Promise((resolve, reject) =>
+ setTimeout(
+ () => reject(new Error('failed to resolve')),
+ resolveDelay,
+ ),
+ ),
+ ErrorComponent: ({ error }) =>
{error.message}
,
+ })
+ const renderWrapper = mount()
+ return new Promise(resolve =>
+ setTimeout(resolve, resolveDelay + 100),
+ ).then(() => expect(renderWrapper).toMatchSnapshot())
+ })
+ })
+ })
+ describe('in a server environment', () => {
+ let oldWindow
+ beforeAll(() => {
+ oldWindow = window
+ global.window = undefined
+ })
+ afterAll(() => {
+ global.window = oldWindow
+ })
+ describe('when an error occurs resolving a component', () => {
+ it('should render the ErrorComponent', () => {
+ const resolveDelay = 10
+ const Bob = asyncComponent({
+ resolve: () =>
+ new Promise((resolve, reject) =>
+ setTimeout(
+ () => reject(new Error('failed to resolve')),
+ resolveDelay,
+ ),
+ ),
+ ErrorComponent: ({ error }) => {error.message}
,
+ })
+ const renderWrapper = mount()
+ return new Promise(resolve =>
+ setTimeout(resolve, resolveDelay + 50),
+ ).then(() => expect(renderWrapper).toMatchSnapshot())
+ })
+ })
+ })
})
diff --git a/src/asyncComponent.js b/src/asyncComponent.js
index 5c09040..231ae57 100644
--- a/src/asyncComponent.js
+++ b/src/asyncComponent.js
@@ -176,6 +176,12 @@ function asyncComponent(config) {
render() {
const { module, error } = this.state
+ if (error) {
+ return ErrorComponent ? (
+
+ ) : null
+ }
+
// This is as workaround for React Hot Loader support. When using
// RHL the local component reference will be killed by any change
// to the component, this will be our signal to know that we need to
@@ -188,12 +194,6 @@ function asyncComponent(config) {
this.resolveModule()
}
- if (error) {
- return ErrorComponent ? (
-
- ) : null
- }
-
const Component = es6Resolve(module)
return Component ? (
diff --git a/umd/react-async-component.js b/umd/react-async-component.js
index f15484f..5256569 100644
--- a/umd/react-async-component.js
+++ b/umd/react-async-component.js
@@ -482,19 +482,19 @@ function asyncComponent(config) {
module = _state.module,
error = _state.error;
+
+ if (error) {
+ return ErrorComponent ? _react2.default.createElement(ErrorComponent, _extends({}, this.props, { error: error })) : null;
+ }
+
// This is as workaround for React Hot Loader support. When using
// RHL the local component reference will be killed by any change
// to the component, this will be our signal to know that we need to
// re-resolve it.
-
if (sharedState.module == null && !this.resolving && typeof window !== 'undefined') {
this.resolveModule();
}
- if (error) {
- return ErrorComponent ? _react2.default.createElement(ErrorComponent, _extends({}, this.props, { error: error })) : null;
- }
-
var Component = es6Resolve(module);
return Component ? _react2.default.createElement(Component, this.props) : LoadingComponent ? _react2.default.createElement(LoadingComponent, this.props) : null;
}
diff --git a/umd/react-async-component.min.js b/umd/react-async-component.min.js
index ea55a5a..239035c 100644
--- a/umd/react-async-component.min.js
+++ b/umd/react-async-component.min.js
@@ -1 +1 @@
-!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("react"),require("prop-types")):"function"==typeof define&&define.amd?define(["react","prop-types"],t):"object"==typeof exports?exports.ReactAsyncComponent=t(require("react"),require("prop-types")):e.ReactAsyncComponent=t(e.React,e.PropTypes)}(this,function(e,t){return function(e){function t(o){if(n[o])return n[o].exports;var r=n[o]={i:o,l:!1,exports:{}};return e[o].call(r.exports,r,r.exports,t),r.l=!0,r.exports}var n={};return t.m=e,t.c=n,t.d=function(e,n,o){t.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:o})},t.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(n,"a",n),n},t.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},t.p="",t(t.s=3)}([function(t,n){t.exports=e},function(e,n){e.exports=t},function(e,t,n){"use strict";function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function r(){var e=0,t={};return{getNextId:function(){return e+=1},resolved:function(e){t[e]=!0},getState:function(){return{resolved:Object.keys(t).reduce(function(e,t){return Object.assign(e,o({},t,!0))},{})}}}}Object.defineProperty(t,"__esModule",{value:!0}),t.default=r},function(e,t,n){"use strict";function o(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0}),t.asyncComponent=t.createAsyncContext=t.AsyncComponentProvider=void 0;var r=n(4),u=o(r),i=n(2),s=o(i),a=n(5),l=o(a);t.AsyncComponentProvider=u.default,t.createAsyncContext=s.default,t.asyncComponent=l.default},function(e,t,n){"use strict";function o(e){return e&&e.__esModule?e:{default:e}}function r(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function u(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function i(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}Object.defineProperty(t,"__esModule",{value:!0});var s=function(){function e(e,t){for(var n=0;n-1?e.env:"undefined"==typeof window?"node":"browser",C={id:null,module:null,error:null,resolver:null},x=function(e){return s&&null!=e&&("function"==typeof e||"object"===(void 0===e?"undefined":c(e)))&&e.default?e.default:e},g=function(){if(null==C.resolver)try{var e=n();C.resolver=Promise.resolve(e)}catch(e){C.resolver=Promise.reject(e)}return C.resolver},w=function(e){function t(e,n){r(this,t);var o=u(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e,n));return o.context.asyncComponents&&!C.id&&(C.id=o.context.asyncComponents.getNextId()),o}return i(t,e),l(t,[{key:"asyncBootstrap",value:function(){var e=this,t=this.context,n=t.asyncComponents,o=t.asyncComponentsAncestor,r=n.shouldRehydrate,u=function(){return e.resolveModule().then(function(e){return void 0!==e})};if("browser"===b)return!!r(C.id)&&u();var i=o&&o.isBoundary;return"defer"!==p&&!i&&u()}},{key:"getChildContext",value:function(){if(this.context.asyncComponents)return{asyncComponentsAncestor:{isBoundary:"boundary"===p}}}},{key:"componentWillMount",value:function(){this.setState({module:C.module}),C.error&&this.registerErrorState(C.error)}},{key:"componentDidMount",value:function(){this.state.module||this.resolveModule()}},{key:"resolveModule",value:function(){var e=this;return this.resolving=!0,g().then(function(t){if(!e.unmounted)return e.context.asyncComponents&&e.context.asyncComponents.resolved(C.id),C.module=t,"browser"===b&&e.setState({module:t}),e.resolving=!1,t}).catch(function(t){e.unmounted||(("node"===b||"browser"===b&&!m)&&(console.warn("Failed to resolve asyncComponent"),console.warn(t)),C.error=t,e.registerErrorState(t),e.resolving=!1)})}},{key:"componentWillUnmount",value:function(){this.unmounted=!0}},{key:"registerErrorState",value:function(e){var t=this;"browser"===b&&setTimeout(function(){t.unmounted||t.setState({error:e})},16)}},{key:"render",value:function(){var e=this.state,t=e.module,n=e.error;if(null!=C.module||this.resolving||"undefined"==typeof window||this.resolveModule(),n)return m?d.default.createElement(m,a({},this.props,{error:n})):null;var o=x(t);return o?d.default.createElement(o,this.props):h?d.default.createElement(h,this.props):null}}]),t}(d.default.Component);return w.displayName=t||"AsyncComponent",w.contextTypes={asyncComponentsAncestor:y.default.shape({isBoundary:y.default.bool}),asyncComponents:y.default.shape({getNextId:y.default.func.isRequired,resolved:y.default.func.isRequired,shouldRehydrate:y.default.func.isRequired})},w.childContextTypes={asyncComponentsAncestor:y.default.shape({isBoundary:y.default.bool})},w}Object.defineProperty(t,"__esModule",{value:!0});var a=Object.assign||function(e){for(var t=1;t-1?e.env:"undefined"==typeof window?"node":"browser",C={id:null,module:null,error:null,resolver:null},x=function(e){return s&&null!=e&&("function"==typeof e||"object"===(void 0===e?"undefined":c(e)))&&e.default?e.default:e},g=function(){if(null==C.resolver)try{var e=n();C.resolver=Promise.resolve(e)}catch(e){C.resolver=Promise.reject(e)}return C.resolver},w=function(e){function t(e,n){r(this,t);var o=u(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e,n));return o.context.asyncComponents&&!C.id&&(C.id=o.context.asyncComponents.getNextId()),o}return i(t,e),l(t,[{key:"asyncBootstrap",value:function(){var e=this,t=this.context,n=t.asyncComponents,o=t.asyncComponentsAncestor,r=n.shouldRehydrate,u=function(){return e.resolveModule().then(function(e){return void 0!==e})};if("browser"===b)return!!r(C.id)&&u();var i=o&&o.isBoundary;return"defer"!==p&&!i&&u()}},{key:"getChildContext",value:function(){if(this.context.asyncComponents)return{asyncComponentsAncestor:{isBoundary:"boundary"===p}}}},{key:"componentWillMount",value:function(){this.setState({module:C.module}),C.error&&this.registerErrorState(C.error)}},{key:"componentDidMount",value:function(){this.state.module||this.resolveModule()}},{key:"resolveModule",value:function(){var e=this;return this.resolving=!0,g().then(function(t){if(!e.unmounted)return e.context.asyncComponents&&e.context.asyncComponents.resolved(C.id),C.module=t,"browser"===b&&e.setState({module:t}),e.resolving=!1,t}).catch(function(t){e.unmounted||(("node"===b||"browser"===b&&!m)&&(console.warn("Failed to resolve asyncComponent"),console.warn(t)),C.error=t,e.registerErrorState(t),e.resolving=!1)})}},{key:"componentWillUnmount",value:function(){this.unmounted=!0}},{key:"registerErrorState",value:function(e){var t=this;"browser"===b&&setTimeout(function(){t.unmounted||t.setState({error:e})},16)}},{key:"render",value:function(){var e=this.state,t=e.module,n=e.error;if(n)return m?d.default.createElement(m,a({},this.props,{error:n})):null;null!=C.module||this.resolving||"undefined"==typeof window||this.resolveModule();var o=x(t);return o?d.default.createElement(o,this.props):h?d.default.createElement(h,this.props):null}}]),t}(d.default.Component);return w.displayName=t||"AsyncComponent",w.contextTypes={asyncComponentsAncestor:y.default.shape({isBoundary:y.default.bool}),asyncComponents:y.default.shape({getNextId:y.default.func.isRequired,resolved:y.default.func.isRequired,shouldRehydrate:y.default.func.isRequired})},w.childContextTypes={asyncComponentsAncestor:y.default.shape({isBoundary:y.default.bool})},w}Object.defineProperty(t,"__esModule",{value:!0});var a=Object.assign||function(e){for(var t=1;t