Skip to content

Commit 8cf9661

Browse files
Merge pull request #1133 from koba04/fix-component-did-update-on-shallow
Fix componentDidUpdate when updating by setState on v16
2 parents efb3913 + 89e2354 commit 8cf9661

File tree

5 files changed

+46
-3
lines changed

5 files changed

+46
-3
lines changed

packages/enzyme-adapter-react-16/src/ReactSixteenAdapter.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,13 @@ function nodeToHostNode(_node) {
146146
}
147147

148148
class ReactSixteenAdapter extends EnzymeAdapter {
149+
constructor() {
150+
super();
151+
this.options = {
152+
...this.options,
153+
enableComponentDidUpdateOnSetState: true,
154+
};
155+
}
149156
createMountRenderer(options) {
150157
assertDomAvailable('mount');
151158
const domNode = options.attachTo || global.document.createElement('div');

packages/enzyme-test-suite/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,4 @@
4141
"react-dom": "^15.5.0"
4242
}
4343
}
44+

packages/enzyme-test-suite/test/ShallowWrapper-spec.jsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3441,8 +3441,7 @@ describe('shallow', () => {
34413441

34423442
context('updating state', () => {
34433443
// NOTE: There is a bug in react 16 shallow renderer where prevContext is not passed
3444-
// into componentDidUpdate. Skip this test for react 16 only. add back in if it gets fixed.
3445-
itIf(!REACT16, 'should call shouldComponentUpdate, componentWillUpdate and componentDidUpdate', () => {
3444+
it('should call shouldComponentUpdate, componentWillUpdate and componentDidUpdate', () => {
34463445
const spy = sinon.spy();
34473446

34483447
class Foo extends React.Component {

packages/enzyme/src/EnzymeAdapter.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ function unimplementedError(methodName, classname) {
55
}
66

77
class EnzymeAdapter {
8+
constructor() {
9+
this.options = {};
10+
}
811
// Provided a bag of options, return an `EnzymeRenderer`. Some options can be implementation
912
// specific, like `attach` etc. for React, but not part of this interface explicitly.
1013
// eslint-disable-next-line class-methods-use-this, no-unused-vars

packages/enzyme/src/ShallowWrapper.js

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -369,7 +369,40 @@ class ShallowWrapper {
369369
}
370370
this.single('setState', () => {
371371
withSetStateAllowed(() => {
372-
this.instance().setState(state, callback);
372+
const adapter = getAdapter(this[OPTIONS]);
373+
const instance = this.instance();
374+
const prevProps = instance.props;
375+
const prevState = instance.state;
376+
const prevContext = instance.context;
377+
let shouldRender = true;
378+
// This is a dirty hack but it requires to know the result of shouldComponentUpdate.
379+
// When shouldComponentUpdate returns false we shouldn't call componentDidUpdate.
380+
// shouldComponentUpdate is called in `instance.setState`
381+
// so we replace shouldComponentUpdate to know the result and restore it later.
382+
let originalShouldComponentUpdate;
383+
if (
384+
this[OPTIONS].lifecycleExperimental &&
385+
adapter.options.enableComponentDidUpdateOnSetState &&
386+
instance &&
387+
typeof instance.shouldComponentUpdate === 'function'
388+
) {
389+
originalShouldComponentUpdate = instance.shouldComponentUpdate;
390+
instance.shouldComponentUpdate = (...args) => {
391+
shouldRender = originalShouldComponentUpdate.apply(instance, args);
392+
instance.shouldComponentUpdate = originalShouldComponentUpdate;
393+
return shouldRender;
394+
};
395+
}
396+
instance.setState(state, callback);
397+
if (
398+
shouldRender &&
399+
this[OPTIONS].lifecycleExperimental &&
400+
adapter.options.enableComponentDidUpdateOnSetState &&
401+
instance &&
402+
typeof instance.componentDidUpdate === 'function'
403+
) {
404+
instance.componentDidUpdate(prevProps, prevState, prevContext);
405+
}
373406
this.update();
374407
});
375408
});

0 commit comments

Comments
 (0)