@samitouri / QOS-React-2 / commits / 2af6d7a702

Should not re-render as the result of a null state update (Stack)

Stack now passes test added in previous commit.

Andrew Clark committed Dec 30, 2016 at 00:14 UTC 2af6d7a70292db15da8f2c678fe77214be8a189d
2 files changed +31 -27
src/renderers/shared/shared/__tests__/ReactUpdates-test.js
+16 -19
@@ -1165,25 +1165,22 @@ describe('ReactUpdates', () => {
1165 expect(called).toEqual(true);
1166 });
1167
1168 - if (ReactDOMFeatureFlags.useFiber) {
1169 - // TODO: Should we add this feature to stack, too?
1170 - it('does not re-render if state update is null', () => {
1171 - let container = document.createElement('div');
1172 -
1173 - let instance;
1174 - let ops = [];
1175 - class Foo extends React.Component {
1176 - render() {
1177 - instance = this;
1178 - ops.push('render');
1179 - return <div />;
1180 - }
1168 + it('does not re-render if state update is null', () => {
1169 + let container = document.createElement('div');
1170 +
1171 + let instance;
1172 + let ops = [];
1173 + class Foo extends React.Component {
1174 + render() {
1175 + instance = this;
1176 + ops.push('render');
1177 + return <div />;
1178 }
1182 - ReactDOM.render(<Foo />, container);
1179 + }
1180 + ReactDOM.render(<Foo />, container);
1181
1184 - ops = [];
1185 - instance.setState(() => null);
1186 - expect(ops).toEqual([]);
1187 - });
1188 - }
1182 + ops = [];
1183 + instance.setState(() => null);
1184 + expect(ops).toEqual([]);
1185 + });
1186 });
src/renderers/shared/stack/reconciler/ReactCompositeComponent.js
+15 -8
@@ -867,8 +867,9 @@ var ReactCompositeComponent = {
867
868 var nextState = this._processPendingState(nextProps, nextContext);
869 var shouldUpdate = true;
870 -
870 if (!this._pendingForceUpdate) {
871 + var prevState = inst.state;
872 + shouldUpdate = willReceive || nextState !== prevState;
873 if (inst.shouldComponentUpdate) {
874 if (__DEV__) {
875 shouldUpdate = measureLifeCyclePerf(
@@ -944,15 +945,21 @@ var ReactCompositeComponent = {
945 return queue[0];
946 }
947
947 - var nextState = Object.assign({}, replace ? queue[0] : inst.state);
948 + var nextState = replace ? queue[0] : inst.state;
949 + var dontMutate = true;
950 for (var i = replace ? 1 : 0; i < queue.length; i++) {
951 var partial = queue[i];
950 - Object.assign(
951 - nextState,
952 - typeof partial === 'function' ?
953 - partial.call(inst, nextState, props, context) :
954 - partial
955 - );
952 + let partialState = typeof partial === 'function' ?
953 + partial.call(inst, nextState, props, context) :
954 + partial;
955 + if (partialState) {
956 + if (dontMutate) {
957 + dontMutate = false;
958 + nextState = Object.assign({}, nextState, partialState);
959 + } else {
960 + Object.assign(nextState, partialState);
961 + }
962 + }
963 }
964
965 return nextState;