diff --git a/src/__tests__/__snapshots__/asyncComponent.test.js.snap b/src/__tests__/__snapshots__/asyncComponent.test.js.snap index e3b0e7b..779303e 100644 --- a/src/__tests__/__snapshots__/asyncComponent.test.js.snap +++ b/src/__tests__/__snapshots__/asyncComponent.test.js.snap @@ -2,4 +2,8 @@ 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 browser environment when multiple instances of component are present should render all instances of the component 1`] = `"
Component
Component
"`; + +exports[`asyncComponent in a browser environment when multiple instances of component are present should render multiple ErrorComponent 1`] = `"
failed to resolve
failed to resolve
"`; + exports[`asyncComponent in a server environment when an error occurs resolving a component should not render the ErrorComponent 1`] = `null`; diff --git a/src/__tests__/asyncComponent.test.js b/src/__tests__/asyncComponent.test.js index a58e35f..244e0eb 100644 --- a/src/__tests__/asyncComponent.test.js +++ b/src/__tests__/asyncComponent.test.js @@ -7,6 +7,7 @@ import asyncComponent from '../asyncComponent' describe('asyncComponent', () => { const errorResolveDelay = 20 + const promiseResolveDelay = 20 describe('in a browser environment', () => { describe('when an error occurs resolving a component', () => { @@ -21,6 +22,39 @@ describe('asyncComponent', () => { expect(renderWrapper.html()).toMatchSnapshot() }) }) + + describe('when multiple instances of component are present', () => { + it('should render all instances of the component', async () => { + const Bob = asyncComponent({ + resolve: () => Promise.resolve(() =>
Component
), + env: 'browser', + }) + const renderWrapper = mount( +
+ + +
, + ) + await new Promise(resolve => setTimeout(resolve, promiseResolveDelay)) + expect(renderWrapper.html()).toMatchSnapshot() + }) + + it('should render multiple ErrorComponent', async () => { + const Bob = asyncComponent({ + resolve: () => Promise.reject(new Error('failed to resolve')), + ErrorComponent: ({ error }) =>
{error.message}
, + env: 'browser', + }) + const renderWrapper = mount( +
+ + +
, + ) + await new Promise(resolve => setTimeout(resolve, errorResolveDelay)) + expect(renderWrapper.html()).toMatchSnapshot() + }) + }) }) describe('in a server environment', () => { diff --git a/src/asyncComponent.js b/src/asyncComponent.js index 4859240..61683c4 100644 --- a/src/asyncComponent.js +++ b/src/asyncComponent.js @@ -42,10 +42,7 @@ export default function asyncComponent(config) { } const needToResolveOnBrowser = () => - state.module == null && - state.error == null && - !state.resolving && - typeof window !== 'undefined' + state.module == null && state.error == null && typeof window !== 'undefined' // Takes the given module and if it has a ".default" the ".default" will // be returned. i.e. handy when you could be dealing with es6 imports. @@ -89,6 +86,13 @@ export default function asyncComponent(config) { }), } + constructor() { + super() + this.state = { + resolving: state.resolving, + } + } + getChildContext() { return { asyncComponentsAncestor: @@ -137,7 +141,9 @@ export default function asyncComponent(config) { } componentDidMount() { - if (needToResolveOnBrowser()) { + const { resolving } = this.state + + if (!resolving && needToResolveOnBrowser()) { this.resolveModule() } }