From 661dbfb3abb7365db44c195b55dc4ece44948242 Mon Sep 17 00:00:00 2001 From: Marvin Hagemeister Date: Thu, 7 Mar 2019 18:54:52 +0100 Subject: [PATCH] Fix stale state if sCU returned false --- src/diff/index.js | 1 + test/browser/lifecycle.test.js | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/src/diff/index.js b/src/diff/index.js index 47b81844a2..e41bd356f4 100644 --- a/src/diff/index.js +++ b/src/diff/index.js @@ -106,6 +106,7 @@ export function diff(dom, parentDom, newVNode, oldVNode, context, isSvg, excessD if (!c._force && c.shouldComponentUpdate!=null && c.shouldComponentUpdate(newVNode.props, s, cctx)===false) { c.props = newVNode.props; + c.state = s; c._dirty = false; break outer; } diff --git a/test/browser/lifecycle.test.js b/test/browser/lifecycle.test.js index daa0006cdc..8c83624a4e 100644 --- a/test/browser/lifecycle.test.js +++ b/test/browser/lifecycle.test.js @@ -1705,6 +1705,40 @@ describe('Lifecycle methods', () => { expect(spy).to.be.calledOnce; }); + + it('should update state reference when sCU returns false', () => { + let spy = sinon.spy(); + + let updateState; + class Foo extends Component { + constructor() { + super(); + this.state = { foo: 1 }; + updateState = () => this.setState({ foo: 2 }); + } + + shouldComponentUpdate(_, nextState) { + if (nextState !== this.state) { + spy(this.state, nextState); + return false; + } + return true; + } + } + + render(, scratch); + updateState(); + rerender(); + + expect(spy).to.be.calledOnce; + expect(spy).to.be.calledWithMatch({ foo: 1 }, { foo: 2 }); + + updateState(); + rerender(); + + expect(spy).to.be.calledWithMatch({ foo: 2 }, { foo: 2 }); + expect(spy).to.be.calledTwice; + }); });