From 16b1f5230a23090d7e2f8ad6214366ed40047c7b Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Sat, 4 May 2019 14:12:50 -0700 Subject: [PATCH] [Fix] `shallow`: properly determine "should render" for `PureComponent`s Fixes #2096. --- .../test/ReactWrapper-spec.jsx | 35 +++++++++++++++++++ .../test/ShallowWrapper-spec.jsx | 33 +++++++++++++++++ packages/enzyme/src/ShallowWrapper.js | 2 +- 3 files changed, 69 insertions(+), 1 deletion(-) diff --git a/packages/enzyme-test-suite/test/ReactWrapper-spec.jsx b/packages/enzyme-test-suite/test/ReactWrapper-spec.jsx index bddcc7988..85b9a8eef 100644 --- a/packages/enzyme-test-suite/test/ReactWrapper-spec.jsx +++ b/packages/enzyme-test-suite/test/ReactWrapper-spec.jsx @@ -3402,6 +3402,41 @@ describeWithDOM('mount', () => { }); }); }); + + it('does not infinitely loop when a PureComponent fires a noop setState in cDU', () => { + class Example extends PureComponent { + constructor(props) { + super(props); + + this.renders = 0; + this.state = { + a: false, + b: false, + }; + } + + componentDidMount() { + this.setState({ b: false }); + } + + componentDidUpdate() { + this.setState({ b: false }); // eslint-disable-line react/no-did-update-set-state + } + + render() { + this.renders += 1; + const { a, b } = this.state; + return
{`${a} ${b} ${this.renders}`}
; + } + } + + const wrapper = mount(); + expect(wrapper.debug()).to.equal(` +
+ false false 1 +
+
`); + }); }); describe('Own PureComponent implementation', () => { diff --git a/packages/enzyme-test-suite/test/ShallowWrapper-spec.jsx b/packages/enzyme-test-suite/test/ShallowWrapper-spec.jsx index 7c58d2025..62cbd98c4 100644 --- a/packages/enzyme-test-suite/test/ShallowWrapper-spec.jsx +++ b/packages/enzyme-test-suite/test/ShallowWrapper-spec.jsx @@ -3802,6 +3802,39 @@ describe('shallow', () => { }); }); }); + + it('does not infinitely loop when a PureComponent fires a noop setState in cDU', () => { + class Example extends PureComponent { + constructor(props) { + super(props); + + this.renders = 0; + this.state = { + a: false, + b: false, + }; + } + + componentDidMount() { + this.setState({ b: false }); + } + + componentDidUpdate() { + this.setState({ b: false }); // eslint-disable-line react/no-did-update-set-state + } + + render() { + this.renders += 1; + const { a, b } = this.state; + return
{`${a} ${b} ${this.renders}`}
; + } + } + + const wrapper = shallow(); + expect(wrapper.debug()).to.equal(`
+ false false 1 +
`); + }); }); describe('Own PureComponent implementation', () => { diff --git a/packages/enzyme/src/ShallowWrapper.js b/packages/enzyme/src/ShallowWrapper.js index 99941e553..c068b3f01 100644 --- a/packages/enzyme/src/ShallowWrapper.js +++ b/packages/enzyme/src/ShallowWrapper.js @@ -778,7 +778,7 @@ class ShallowWrapper { prevProps, instance.props, prevState, - statePayload, + { ...prevState, ...statePayload }, ); }