From 2af6d7a70292db15da8f2c678fe77214be8a189d Mon Sep 17 00:00:00 2001 From: Andrew Clark Date: Fri, 30 Dec 2016 00:14:06 -0800 Subject: [PATCH] Should not re-render as the result of a null state update (Stack) Stack now passes test added in previous commit. --- .../shared/__tests__/ReactUpdates-test.js | 33 +++++++++---------- .../reconciler/ReactCompositeComponent.js | 23 ++++++++----- 2 files changed, 30 insertions(+), 26 deletions(-) diff --git a/src/renderers/shared/shared/__tests__/ReactUpdates-test.js b/src/renderers/shared/shared/__tests__/ReactUpdates-test.js index 8464559be0..ef44d56a9f 100644 --- a/src/renderers/shared/shared/__tests__/ReactUpdates-test.js +++ b/src/renderers/shared/shared/__tests__/ReactUpdates-test.js @@ -1165,25 +1165,22 @@ describe('ReactUpdates', () => { expect(called).toEqual(true); }); - if (ReactDOMFeatureFlags.useFiber) { - // TODO: Should we add this feature to stack, too? - it('does not re-render if state update is null', () => { - let container = document.createElement('div'); + it('does not re-render if state update is null', () => { + let container = document.createElement('div'); - let instance; - let ops = []; - class Foo extends React.Component { - render() { - instance = this; - ops.push('render'); - return
; - } + let instance; + let ops = []; + class Foo extends React.Component { + render() { + instance = this; + ops.push('render'); + return
; } - ReactDOM.render(, container); + } + ReactDOM.render(, container); - ops = []; - instance.setState(() => null); - expect(ops).toEqual([]); - }); - } + ops = []; + instance.setState(() => null); + expect(ops).toEqual([]); + }); }); diff --git a/src/renderers/shared/stack/reconciler/ReactCompositeComponent.js b/src/renderers/shared/stack/reconciler/ReactCompositeComponent.js index 8fdaec8c1b..79baf74489 100644 --- a/src/renderers/shared/stack/reconciler/ReactCompositeComponent.js +++ b/src/renderers/shared/stack/reconciler/ReactCompositeComponent.js @@ -867,8 +867,9 @@ var ReactCompositeComponent = { var nextState = this._processPendingState(nextProps, nextContext); var shouldUpdate = true; - if (!this._pendingForceUpdate) { + var prevState = inst.state; + shouldUpdate = willReceive || nextState !== prevState; if (inst.shouldComponentUpdate) { if (__DEV__) { shouldUpdate = measureLifeCyclePerf( @@ -944,15 +945,21 @@ var ReactCompositeComponent = { return queue[0]; } - var nextState = Object.assign({}, replace ? queue[0] : inst.state); + var nextState = replace ? queue[0] : inst.state; + var dontMutate = true; for (var i = replace ? 1 : 0; i < queue.length; i++) { var partial = queue[i]; - Object.assign( - nextState, - typeof partial === 'function' ? - partial.call(inst, nextState, props, context) : - partial - ); + let partialState = typeof partial === 'function' ? + partial.call(inst, nextState, props, context) : + partial; + if (partialState) { + if (dontMutate) { + dontMutate = false; + nextState = Object.assign({}, nextState, partialState); + } else { + Object.assign(nextState, partialState); + } + } } return nextState;