From a48101688386855be96052176dbadb18583ea348 Mon Sep 17 00:00:00 2001 From: Sebastian Markbage Date: Sun, 20 Nov 2016 21:28:54 +0000 Subject: [PATCH] Preserve the original object when using replaceState When we use only replace state we don't need to clone the object. --- scripts/fiber/tests-failing.txt | 1 - scripts/fiber/tests-passing.txt | 1 + .../shared/fiber/ReactFiberUpdateQueue.js | 29 +++++++++++++------ 3 files changed, 21 insertions(+), 10 deletions(-) diff --git a/scripts/fiber/tests-failing.txt b/scripts/fiber/tests-failing.txt index 712f9b98bd..c5979c37a4 100644 --- a/scripts/fiber/tests-failing.txt +++ b/scripts/fiber/tests-failing.txt @@ -114,7 +114,6 @@ src/renderers/shared/stack/reconciler/__tests__/ReactCompositeComponent-test.js * should warn about `setState` in render * should warn about `setState` in getChildContext * should update refs if shouldComponentUpdate gives false -* should support objects with prototypes as state src/renderers/shared/stack/reconciler/__tests__/ReactCompositeComponentNestedState-test.js * should provide up to date values for props diff --git a/scripts/fiber/tests-passing.txt b/scripts/fiber/tests-passing.txt index 62b88a8aa7..27de2c82c3 100644 --- a/scripts/fiber/tests-passing.txt +++ b/scripts/fiber/tests-passing.txt @@ -1284,6 +1284,7 @@ src/renderers/shared/stack/reconciler/__tests__/ReactCompositeComponent-test.js * should allow access to findDOMNode in componentWillUnmount * context should be passed down from the parent * should replace state +* should support objects with prototypes as state * should not warn about unmounting during unmounting * should only call componentWillUnmount once diff --git a/src/renderers/shared/fiber/ReactFiberUpdateQueue.js b/src/renderers/shared/fiber/ReactFiberUpdateQueue.js index 83d8542f51..784e8b8a6b 100644 --- a/src/renderers/shared/fiber/ReactFiberUpdateQueue.js +++ b/src/renderers/shared/fiber/ReactFiberUpdateQueue.js @@ -87,19 +87,30 @@ exports.callCallbacks = function(queue : UpdateQueue, context : any) : Error | n return firstError; }; +function getStateFromNode(node, instance, state, props) { + if (typeof node.partialState === 'function') { + const updateFn = node.partialState; + return updateFn.call(instance, state, props); + } else { + return node.partialState; + } +} + exports.mergeUpdateQueue = function(queue : UpdateQueue, instance : any, prevState : any, props : any) : any { let node : ?UpdateQueueNode = queue; + if (queue.isReplace) { + // replaceState is always first in the queue. + prevState = getStateFromNode(queue, instance, prevState, props); + node = queue.next; + if (!node) { + // If there is no more work, we replace the raw object instead of cloning. + return prevState; + } + } let state = Object.assign({}, prevState); while (node) { - state = node.isReplace ? null : state; - let partialState; - if (typeof node.partialState === 'function') { - const updateFn = node.partialState; - partialState = updateFn.call(instance, state, props); - } else { - partialState = node.partialState; - } - state = Object.assign(state || {}, partialState); + let partialState = getStateFromNode(node, instance, state, props); + Object.assign(state, partialState); node = node.next; } return state;