diff --git a/packages/enzyme-test-suite/test/ReactWrapper-spec.jsx b/packages/enzyme-test-suite/test/ReactWrapper-spec.jsx
index 60bcf82ff..4c88c84af 100644
--- a/packages/enzyme-test-suite/test/ReactWrapper-spec.jsx
+++ b/packages/enzyme-test-suite/test/ReactWrapper-spec.jsx
@@ -5196,5 +5196,35 @@ describeWithDOM('mount', () => {
expect(spy).to.have.property('callCount', 1);
expect(wrapper.state('foo')).to.equal('update');
});
+
+ it('should not call `componentDidMount` twice when a child component is created', () => {
+ class Foo extends React.Component {
+ constructor(props) {
+ super(props);
+ this.state = {
+ foo: 'init',
+ };
+ }
+
+ componentDidMount() {}
+
+ render() {
+ return (
+
+
+ {this.state.foo}
+
+ );
+ }
+ }
+ const spy = sinon.spy(Foo.prototype, 'componentDidMount');
+
+ const wrapper = mount();
+ expect(spy).to.have.property('callCount', 1);
+ wrapper.find('button').prop('onClick')();
+ expect(spy).to.have.property('callCount', 1);
+ });
});
});
diff --git a/packages/enzyme-test-suite/test/ShallowWrapper-spec.jsx b/packages/enzyme-test-suite/test/ShallowWrapper-spec.jsx
index 2745b9faa..4418fe35a 100644
--- a/packages/enzyme-test-suite/test/ShallowWrapper-spec.jsx
+++ b/packages/enzyme-test-suite/test/ShallowWrapper-spec.jsx
@@ -4994,6 +4994,36 @@ describe('shallow', () => {
expect(spy).to.have.property('callCount', 1);
expect(wrapper.state('foo')).to.equal('update');
});
+
+ it('should not call `componentDidMount` twice when a child component is created', () => {
+ class Foo extends React.Component {
+ constructor(props) {
+ super(props);
+ this.state = {
+ foo: 'init',
+ };
+ }
+
+ componentDidMount() {}
+
+ render() {
+ return (
+
+
+ {this.state.foo}
+
+ );
+ }
+ }
+ const spy = sinon.spy(Foo.prototype, 'componentDidMount');
+
+ const wrapper = shallow();
+ expect(spy).to.have.property('callCount', 1);
+ wrapper.find('button').prop('onClick')();
+ expect(spy).to.have.property('callCount', 1);
+ });
});
describeIf(is('>= 16'), 'support getSnapshotBeforeUpdate', () => {
diff --git a/packages/enzyme/src/ShallowWrapper.js b/packages/enzyme/src/ShallowWrapper.js
index e7f774755..ff1c5e40b 100644
--- a/packages/enzyme/src/ShallowWrapper.js
+++ b/packages/enzyme/src/ShallowWrapper.js
@@ -168,37 +168,38 @@ class ShallowWrapper {
const adapter = getAdapter(options);
const lifecycles = getAdapterLifecycles(adapter);
- let renderedNode;
+ // mounting a ShallowRender component
if (!root) {
privateSet(this, ROOT, this);
privateSet(this, UNRENDERED, nodes);
const renderer = adapter.createRenderer({ mode: 'shallow', ...options });
privateSet(this, RENDERER, renderer);
this[RENDERER].render(nodes, options.context);
- renderedNode = this[RENDERER].getNode();
+ const renderedNode = this[RENDERER].getNode();
privateSetNodes(this, getRootNode(renderedNode));
+ privateSet(this, OPTIONS, options);
+
+ const { instance } = renderedNode;
+ if (instance && !options.disableLifecycleMethods) {
+ // Ensure to call componentDidUpdate when instance.setState is called
+ if (lifecycles.componentDidUpdate.onSetState && !instance[SET_STATE]) {
+ privateSet(instance, SET_STATE, instance.setState);
+ instance.setState = (...args) => this.setState(...args);
+ }
+
+ if (typeof instance.componentDidMount === 'function') {
+ this[RENDERER].batchedUpdates(() => {
+ instance.componentDidMount();
+ });
+ }
+ }
+ // creating a child component through enzyme's ShallowWrapper APIs.
} else {
privateSet(this, ROOT, root);
privateSet(this, UNRENDERED, null);
privateSet(this, RENDERER, root[RENDERER]);
privateSetNodes(this, nodes);
- renderedNode = this[RENDERER].getNode();
- }
- privateSet(this, OPTIONS, root ? root[OPTIONS] : options);
-
- const { instance } = renderedNode;
- if (instance && !options.disableLifecycleMethods) {
- // Ensure to call componentDidUpdate when instance.setState is called
- if (lifecycles.componentDidUpdate.onSetState && !instance[SET_STATE]) {
- privateSet(instance, SET_STATE, instance.setState);
- instance.setState = (...args) => this.setState(...args);
- }
-
- if (typeof instance.componentDidMount === 'function') {
- this[RENDERER].batchedUpdates(() => {
- instance.componentDidMount();
- });
- }
+ privateSet(this, OPTIONS, root[OPTIONS]);
}
}